From: Apple Date: Thu, 7 Sep 2006 04:43:12 +0000 (+0000) Subject: mDNSResponder-107.6.tar.gz X-Git-Tag: v107.6^0 X-Git-Url: https://git.saurik.com/apple/mdnsresponder.git/commitdiff_plain/619ee211a2d1cd19533acb8c109cb34a602cbd46 mDNSResponder-107.6.tar.gz --- diff --git a/APPLE_LICENSE b/APPLE_LICENSE deleted file mode 100644 index fe81a60..0000000 --- a/APPLE_LICENSE +++ /dev/null @@ -1,367 +0,0 @@ -APPLE PUBLIC SOURCE LICENSE -Version 2.0 - August 6, 2003 - -Please read this License carefully before downloading this software. -By downloading or using this software, you are agreeing to be bound by -the terms of this License. If you do not or cannot agree to the terms -of this License, please do not download or use the software. - -1. General; Definitions. This License applies to any program or other -work which Apple Computer, Inc. ("Apple") makes publicly available and -which contains a notice placed by Apple identifying such program or -work as "Original Code" and stating that it is subject to the terms of -this Apple Public Source License version 2.0 ("License"). As used in -this License: - -1.1 "Applicable Patent Rights" mean: (a) in the case where Apple is -the grantor of rights, (i) claims of patents that are now or hereafter -acquired, owned by or assigned to Apple and (ii) that cover subject -matter contained in the Original Code, but only to the extent -necessary to use, reproduce and/or distribute the Original Code -without infringement; and (b) in the case where You are the grantor of -rights, (i) claims of patents that are now or hereafter acquired, -owned by or assigned to You and (ii) that cover subject matter in Your -Modifications, taken alone or in combination with Original Code. - -1.2 "Contributor" means any person or entity that creates or -contributes to the creation of Modifications. - -1.3 "Covered Code" means the Original Code, Modifications, the -combination of Original Code and any Modifications, and/or any -respective portions thereof. - -1.4 "Externally Deploy" means: (a) to sublicense, distribute or -otherwise make Covered Code available, directly or indirectly, to -anyone other than You; and/or (b) to use Covered Code, alone or as -part of a Larger Work, in any way to provide a service, including but -not limited to delivery of content, through electronic communication -with a client other than You. - -1.5 "Larger Work" means a work which combines Covered Code or portions -thereof with code not governed by the terms of this License. - -1.6 "Modifications" mean any addition to, deletion from, and/or change -to, the substance and/or structure of the Original Code, any previous -Modifications, the combination of Original Code and any previous -Modifications, and/or any respective portions thereof. When code is -released as a series of files, a Modification is: (a) any addition to -or deletion from the contents of a file containing Covered Code; -and/or (b) any new file or other representation of computer program -statements that contains any part of Covered Code. - -1.7 "Original Code" means (a) the Source Code of a program or other -work as originally made available by Apple under this License, -including the Source Code of any updates or upgrades to such programs -or works made available by Apple under this License, and that has been -expressly identified by Apple as such in the header file(s) of such -work; and (b) the object code compiled from such Source Code and -originally made available by Apple under this License. - -1.8 "Source Code" means the human readable form of a program or other -work that is suitable for making modifications to it, including all -modules it contains, plus any associated interface definition files, -scripts used to control compilation and installation of an executable -(object code). - -1.9 "You" or "Your" means an individual or a legal entity exercising -rights under this License. For legal entities, "You" or "Your" -includes any entity which controls, is controlled by, or is under -common control with, You, where "control" means (a) the power, direct -or indirect, to cause the direction or management of such entity, -whether by contract or otherwise, or (b) ownership of fifty percent -(50%) or more of the outstanding shares or beneficial ownership of -such entity. - -2. Permitted Uses; Conditions & Restrictions. Subject to the terms -and conditions of this License, Apple hereby grants You, effective on -the date You accept this License and download the Original Code, a -world-wide, royalty-free, non-exclusive license, to the extent of -Apple's Applicable Patent Rights and copyrights covering the Original -Code, to do the following: - -2.1 Unmodified Code. You may use, reproduce, display, perform, -internally distribute within Your organization, and Externally Deploy -verbatim, unmodified copies of the Original Code, for commercial or -non-commercial purposes, provided that in each instance: - -(a) You must retain and reproduce in all copies of Original Code the -copyright and other proprietary notices and disclaimers of Apple as -they appear in the Original Code, and keep intact all notices in the -Original Code that refer to this License; and - -(b) You must include a copy of this License with every copy of Source -Code of Covered Code and documentation You distribute or Externally -Deploy, and You may not offer or impose any terms on such Source Code -that alter or restrict this License or the recipients' rights -hereunder, except as permitted under Section 6. - -2.2 Modified Code. You may modify Covered Code and use, reproduce, -display, perform, internally distribute within Your organization, and -Externally Deploy Your Modifications and Covered Code, for commercial -or non-commercial purposes, provided that in each instance You also -meet all of these conditions: - -(a) You must satisfy all the conditions of Section 2.1 with respect to -the Source Code of the Covered Code; - -(b) You must duplicate, to the extent it does not already exist, the -notice in Exhibit A in each file of the Source Code of all Your -Modifications, and cause the modified files to carry prominent notices -stating that You changed the files and the date of any change; and - -(c) If You Externally Deploy Your Modifications, You must make -Source Code of all Your Externally Deployed Modifications either -available to those to whom You have Externally Deployed Your -Modifications, or publicly available. Source Code of Your Externally -Deployed Modifications must be released under the terms set forth in -this License, including the license grants set forth in Section 3 -below, for as long as you Externally Deploy the Covered Code or twelve -(12) months from the date of initial External Deployment, whichever is -longer. You should preferably distribute the Source Code of Your -Externally Deployed Modifications electronically (e.g. download from a -web site). - -2.3 Distribution of Executable Versions. In addition, if You -Externally Deploy Covered Code (Original Code and/or Modifications) in -object code, executable form only, You must include a prominent -notice, in the code itself as well as in related documentation, -stating that Source Code of the Covered Code is available under the -terms of this License with information on how and where to obtain such -Source Code. - -2.4 Third Party Rights. You expressly acknowledge and agree that -although Apple and each Contributor grants the licenses to their -respective portions of the Covered Code set forth herein, no -assurances are provided by Apple or any Contributor that the Covered -Code does not infringe the patent or other intellectual property -rights of any other entity. Apple and each Contributor disclaim any -liability to You for claims brought by any other entity based on -infringement of intellectual property rights or otherwise. As a -condition to exercising the rights and licenses granted hereunder, You -hereby assume sole responsibility to secure any other intellectual -property rights needed, if any. For example, if a third party patent -license is required to allow You to distribute the Covered Code, it is -Your responsibility to acquire that license before distributing the -Covered Code. - -3. Your Grants. In consideration of, and as a condition to, the -licenses granted to You under this License, You hereby grant to any -person or entity receiving or distributing Covered Code under this -License a non-exclusive, royalty-free, perpetual, irrevocable license, -under Your Applicable Patent Rights and other intellectual property -rights (other than patent) owned or controlled by You, to use, -reproduce, display, perform, modify, sublicense, distribute and -Externally Deploy Your Modifications of the same scope and extent as -Apple's licenses under Sections 2.1 and 2.2 above. - -4. Larger Works. You may create a Larger Work by combining Covered -Code with other code not governed by the terms of this License and -distribute the Larger Work as a single product. In each such instance, -You must make sure the requirements of this License are fulfilled for -the Covered Code or any portion thereof. - -5. Limitations on Patent License. Except as expressly stated in -Section 2, no other patent rights, express or implied, are granted by -Apple herein. Modifications and/or Larger Works may require additional -patent licenses from Apple which Apple may grant in its sole -discretion. - -6. Additional Terms. You may choose to offer, and to charge a fee for, -warranty, support, indemnity or liability obligations and/or other -rights consistent with the scope of the license granted herein -("Additional Terms") to one or more recipients of Covered Code. -However, You may do so only on Your own behalf and as Your sole -responsibility, and not on behalf of Apple or any Contributor. You -must obtain the recipient's agreement that any such Additional Terms -are offered by You alone, and You hereby agree to indemnify, defend -and hold Apple and every Contributor harmless for any liability -incurred by or claims asserted against Apple or such Contributor by -reason of any such Additional Terms. - -7. Versions of the License. Apple may publish revised and/or new -versions of this License from time to time. Each version will be given -a distinguishing version number. Once Original Code has been published -under a particular version of this License, You may continue to use it -under the terms of that version. You may also choose to use such -Original Code under the terms of any subsequent version of this -License published by Apple. No one other than Apple has the right to -modify the terms applicable to Covered Code created under this -License. - -8. NO WARRANTY OR SUPPORT. The Covered Code may contain in whole or in -part pre-release, untested, or not fully tested works. The Covered -Code may contain errors that could cause failures or loss of data, and -may be incomplete or contain inaccuracies. You expressly acknowledge -and agree that use of the Covered Code, or any portion thereof, is at -Your sole and entire risk. THE COVERED CODE IS PROVIDED "AS IS" AND -WITHOUT WARRANTY, UPGRADES OR SUPPORT OF ANY KIND AND APPLE AND -APPLE'S LICENSOR(S) (COLLECTIVELY REFERRED TO AS "APPLE" FOR THE -PURPOSES OF SECTIONS 8 AND 9) AND ALL CONTRIBUTORS EXPRESSLY DISCLAIM -ALL WARRANTIES AND/OR CONDITIONS, EXPRESS OR IMPLIED, INCLUDING, BUT -NOT LIMITED TO, THE IMPLIED WARRANTIES AND/OR CONDITIONS OF -MERCHANTABILITY, OF SATISFACTORY QUALITY, OF FITNESS FOR A PARTICULAR -PURPOSE, OF ACCURACY, OF QUIET ENJOYMENT, AND NONINFRINGEMENT OF THIRD -PARTY RIGHTS. APPLE AND EACH CONTRIBUTOR DOES NOT WARRANT AGAINST -INTERFERENCE WITH YOUR ENJOYMENT OF THE COVERED CODE, THAT THE -FUNCTIONS CONTAINED IN THE COVERED CODE WILL MEET YOUR REQUIREMENTS, -THAT THE OPERATION OF THE COVERED CODE WILL BE UNINTERRUPTED OR -ERROR-FREE, OR THAT DEFECTS IN THE COVERED CODE WILL BE CORRECTED. NO -ORAL OR WRITTEN INFORMATION OR ADVICE GIVEN BY APPLE, AN APPLE -AUTHORIZED REPRESENTATIVE OR ANY CONTRIBUTOR SHALL CREATE A WARRANTY. -You acknowledge that the Covered Code is not intended for use in the -operation of nuclear facilities, aircraft navigation, communication -systems, or air traffic control machines in which case the failure of -the Covered Code could lead to death, personal injury, or severe -physical or environmental damage. - -9. LIMITATION OF LIABILITY. TO THE EXTENT NOT PROHIBITED BY LAW, IN NO -EVENT SHALL APPLE OR ANY CONTRIBUTOR BE LIABLE FOR ANY INCIDENTAL, -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING -TO THIS LICENSE OR YOUR USE OR INABILITY TO USE THE COVERED CODE, OR -ANY PORTION THEREOF, WHETHER UNDER A THEORY OF CONTRACT, WARRANTY, -TORT (INCLUDING NEGLIGENCE), PRODUCTS LIABILITY OR OTHERWISE, EVEN IF -APPLE OR SUCH CONTRIBUTOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES AND NOTWITHSTANDING THE FAILURE OF ESSENTIAL PURPOSE OF ANY -REMEDY. SOME JURISDICTIONS DO NOT ALLOW THE LIMITATION OF LIABILITY OF -INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS LIMITATION MAY NOT APPLY -TO YOU. In no event shall Apple's total liability to You for all -damages (other than as may be required by applicable law) under this -License exceed the amount of fifty dollars ($50.00). - -10. Trademarks. This License does not grant any rights to use the -trademarks or trade names "Apple", "Apple Computer", "Mac", "Mac OS", -"QuickTime", "QuickTime Streaming Server" or any other trademarks, -service marks, logos or trade names belonging to Apple (collectively -"Apple Marks") or to any trademark, service mark, logo or trade name -belonging to any Contributor. You agree not to use any Apple Marks in -or as part of the name of products derived from the Original Code or -to endorse or promote products derived from the Original Code other -than as expressly permitted by and in strict compliance at all times -with Apple's third party trademark usage guidelines which are posted -at http://www.apple.com/legal/guidelinesfor3rdparties.html. - -11. Ownership. Subject to the licenses granted under this License, -each Contributor retains all rights, title and interest in and to any -Modifications made by such Contributor. Apple retains all rights, -title and interest in and to the Original Code and any Modifications -made by or on behalf of Apple ("Apple Modifications"), and such Apple -Modifications will not be automatically subject to this License. Apple -may, at its sole discretion, choose to license such Apple -Modifications under this License, or on different terms from those -contained in this License or may choose not to license them at all. - -12. Termination. - -12.1 Termination. This License and the rights granted hereunder will -terminate: - -(a) automatically without notice from Apple if You fail to comply with -any term(s) of this License and fail to cure such breach within 30 -days of becoming aware of such breach; - -(b) immediately in the event of the circumstances described in Section -13.5(b); or - -(c) automatically without notice from Apple if You, at any time during -the term of this License, commence an action for patent infringement -against Apple; provided that Apple did not first commence -an action for patent infringement against You in that instance. - -12.2 Effect of Termination. Upon termination, You agree to immediately -stop any further use, reproduction, modification, sublicensing and -distribution of the Covered Code. All sublicenses to the Covered Code -which have been properly granted prior to termination shall survive -any termination of this License. Provisions which, by their nature, -should remain in effect beyond the termination of this License shall -survive, including but not limited to Sections 3, 5, 8, 9, 10, 11, -12.2 and 13. No party will be liable to any other for compensation, -indemnity or damages of any sort solely as a result of terminating -this License in accordance with its terms, and termination of this -License will be without prejudice to any other right or remedy of -any party. - -13. Miscellaneous. - -13.1 Government End Users. The Covered Code is a "commercial item" as -defined in FAR 2.101. Government software and technical data rights in -the Covered Code include only those rights customarily provided to the -public as defined in this License. This customary commercial license -in technical data and software is provided in accordance with FAR -12.211 (Technical Data) and 12.212 (Computer Software) and, for -Department of Defense purchases, DFAR 252.227-7015 (Technical Data -- -Commercial Items) and 227.7202-3 (Rights in Commercial Computer -Software or Computer Software Documentation). Accordingly, all U.S. -Government End Users acquire Covered Code with only those rights set -forth herein. - -13.2 Relationship of Parties. This License will not be construed as -creating an agency, partnership, joint venture or any other form of -legal association between or among You, Apple or any Contributor, and -You will not represent to the contrary, whether expressly, by -implication, appearance or otherwise. - -13.3 Independent Development. Nothing in this License will impair -Apple's right to acquire, license, develop, have others develop for -it, market and/or distribute technology or products that perform the -same or similar functions as, or otherwise compete with, -Modifications, Larger Works, technology or products that You may -develop, produce, market or distribute. - -13.4 Waiver; Construction. Failure by Apple or any Contributor to -enforce any provision of this License will not be deemed a waiver of -future enforcement of that or any other provision. Any law or -regulation which provides that the language of a contract shall be -construed against the drafter will not apply to this License. - -13.5 Severability. (a) If for any reason a court of competent -jurisdiction finds any provision of this License, or portion thereof, -to be unenforceable, that provision of the License will be enforced to -the maximum extent permissible so as to effect the economic benefits -and intent of the parties, and the remainder of this License will -continue in full force and effect. (b) Notwithstanding the foregoing, -if applicable law prohibits or restricts You from fully and/or -specifically complying with Sections 2 and/or 3 or prevents the -enforceability of either of those Sections, this License will -immediately terminate and You must immediately discontinue any use of -the Covered Code and destroy all copies of it that are in your -possession or control. - -13.6 Dispute Resolution. Any litigation or other dispute resolution -between You and Apple relating to this License shall take place in the -Northern District of California, and You and Apple hereby consent to -the personal jurisdiction of, and venue in, the state and federal -courts within that District with respect to this License. The -application of the United Nations Convention on Contracts for the -International Sale of Goods is expressly excluded. - -13.7 Entire Agreement; Governing Law. This License constitutes the -entire agreement between the parties with respect to the subject -matter hereof. This License shall be governed by the laws of the -United States and the State of California, except that body of -California law concerning conflicts of law. - -Where You are located in the province of Quebec, Canada, the following -clause applies: The parties hereby confirm that they have requested -that this License and all related documents be drafted in English. Les -parties ont exige que le present contrat et tous les documents -connexes soient rediges en anglais. - -EXHIBIT A. - -"Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights -Reserved. - -This file contains Original Code and/or Modifications of Original Code -as defined in and that are subject to the Apple Public Source License -Version 2.0 (the 'License'). You may not use this file except in -compliance with the License. Please obtain a copy of the License at -http://www.opensource.apple.com/apsl/ and read it before using this -file. - -The Original Code and all software distributed under the License are -distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER -EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, -INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. -Please see the License for the specific language governing rights and -limitations under the License." diff --git a/Clients/BonjourExample/BonjourExample.cpp b/Clients/BonjourExample/BonjourExample.cpp index ec448f4..ff50a39 100644 --- a/Clients/BonjourExample/BonjourExample.cpp +++ b/Clients/BonjourExample/BonjourExample.cpp @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 2005 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: BonjourExample.cpp,v $ +Revision 1.2 2006/08/14 23:23:57 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.1 2005/05/20 22:01:01 bradley Bonjour for Windows example code to browse for HTTP services and deliver via Window messages. diff --git a/Clients/BonjourExample/stdafx.cpp b/Clients/BonjourExample/stdafx.cpp index 2b2483e..c6899cd 100644 --- a/Clients/BonjourExample/stdafx.cpp +++ b/Clients/BonjourExample/stdafx.cpp @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 2005 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: stdafx.cpp,v $ +Revision 1.2 2006/08/14 23:23:57 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.1 2005/05/20 22:01:02 bradley Bonjour for Windows example code to browse for HTTP services and deliver via Window messages. diff --git a/Clients/BonjourExample/stdafx.h b/Clients/BonjourExample/stdafx.h index 6ded040..461d119 100644 --- a/Clients/BonjourExample/stdafx.h +++ b/Clients/BonjourExample/stdafx.h @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 2005 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: stdafx.h,v $ +Revision 1.2 2006/08/14 23:23:57 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.1 2005/05/20 22:01:02 bradley Bonjour for Windows example code to browse for HTTP services and deliver via Window messages. diff --git a/Clients/DNSServiceBrowser.NET/AssemblyInfo.cs b/Clients/DNSServiceBrowser.NET/AssemblyInfo.cs index 793362b..588f438 100755 --- a/Clients/DNSServiceBrowser.NET/AssemblyInfo.cs +++ b/Clients/DNSServiceBrowser.NET/AssemblyInfo.cs @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 1997-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: AssemblyInfo.cs,v $ +Revision 1.2 2006/08/14 23:23:58 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.1 2004/07/19 07:54:24 shersche Initial revision diff --git a/Clients/DNSServiceBrowser.NET/DNSServiceBrowser.cs b/Clients/DNSServiceBrowser.NET/DNSServiceBrowser.cs index f2cf813..e279d18 100755 --- a/Clients/DNSServiceBrowser.NET/DNSServiceBrowser.cs +++ b/Clients/DNSServiceBrowser.NET/DNSServiceBrowser.cs @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 1997-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: DNSServiceBrowser.cs,v $ +Revision 1.7 2006/08/14 23:23:58 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.6 2005/02/10 22:35:06 cheshire Update name diff --git a/Clients/DNSServiceBrowser.m b/Clients/DNSServiceBrowser.m index da42780..2394a6a 100755 --- a/Clients/DNSServiceBrowser.m +++ b/Clients/DNSServiceBrowser.m @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: DNSServiceBrowser.m,v $ +Revision 1.31 2006/08/14 23:23:55 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.30 2005/01/27 17:46:16 cheshire Added comment diff --git a/Clients/DNSServiceReg.m b/Clients/DNSServiceReg.m index c4a3ee7..49e0c36 100644 --- a/Clients/DNSServiceReg.m +++ b/Clients/DNSServiceReg.m @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: DNSServiceReg.m,v $ +Revision 1.16 2006/08/14 23:23:55 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.15 2004/06/05 02:01:08 cheshire Move DNSServiceRegistration from mDNSMacOSX directory to Clients directory diff --git a/Clients/ExplorerPlugin/ClassFactory.cpp b/Clients/ExplorerPlugin/ClassFactory.cpp index b4e06c6..f77e182 100644 --- a/Clients/ExplorerPlugin/ClassFactory.cpp +++ b/Clients/ExplorerPlugin/ClassFactory.cpp @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: ClassFactory.cpp,v $ +Revision 1.3 2006/08/14 23:24:00 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.2 2004/07/13 21:24:21 rpantos Fix for . diff --git a/Clients/ExplorerPlugin/ClassFactory.h b/Clients/ExplorerPlugin/ClassFactory.h index 76e4b5e..f5fe9d5 100644 --- a/Clients/ExplorerPlugin/ClassFactory.h +++ b/Clients/ExplorerPlugin/ClassFactory.h @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: ClassFactory.h,v $ +Revision 1.3 2006/08/14 23:24:00 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.2 2004/07/13 21:24:21 rpantos Fix for . diff --git a/Clients/ExplorerPlugin/ExplorerBar.cpp b/Clients/ExplorerPlugin/ExplorerBar.cpp index 1c71c9b..f09d983 100644 --- a/Clients/ExplorerPlugin/ExplorerBar.cpp +++ b/Clients/ExplorerPlugin/ExplorerBar.cpp @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: ExplorerBar.cpp,v $ +Revision 1.4 2006/08/14 23:24:00 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.3 2004/07/26 05:44:08 shersche remove extraneous debug statement diff --git a/Clients/ExplorerPlugin/ExplorerBar.h b/Clients/ExplorerPlugin/ExplorerBar.h index fe58176..5af86eb 100644 --- a/Clients/ExplorerPlugin/ExplorerBar.h +++ b/Clients/ExplorerPlugin/ExplorerBar.h @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: ExplorerBar.h,v $ +Revision 1.3 2006/08/14 23:24:00 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.2 2004/07/13 21:24:21 rpantos Fix for . diff --git a/Clients/ExplorerPlugin/ExplorerBarWindow.cpp b/Clients/ExplorerPlugin/ExplorerBarWindow.cpp index d4ea5c1..88f4858 100644 --- a/Clients/ExplorerPlugin/ExplorerBarWindow.cpp +++ b/Clients/ExplorerPlugin/ExplorerBarWindow.cpp @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: ExplorerBarWindow.cpp,v $ +Revision 1.22 2006/08/14 23:24:00 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.21 2005/04/06 01:13:07 shersche Use the product icon instead of globe icon for 'About' link. diff --git a/Clients/ExplorerPlugin/ExplorerBarWindow.h b/Clients/ExplorerPlugin/ExplorerBarWindow.h index deade95..f035872 100644 --- a/Clients/ExplorerPlugin/ExplorerBarWindow.h +++ b/Clients/ExplorerPlugin/ExplorerBarWindow.h @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: ExplorerBarWindow.h,v $ +Revision 1.8 2006/08/14 23:24:00 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.7 2005/02/25 19:57:30 shersche Remove FTP browsing from plugin diff --git a/Clients/ExplorerPlugin/ExplorerPlugin.cpp b/Clients/ExplorerPlugin/ExplorerPlugin.cpp index 34b981e..c2c661b 100644 --- a/Clients/ExplorerPlugin/ExplorerPlugin.cpp +++ b/Clients/ExplorerPlugin/ExplorerPlugin.cpp @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: ExplorerPlugin.cpp,v $ +Revision 1.9 2006/08/14 23:24:00 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.8 2005/06/30 18:01:54 shersche Cause IE to rebuild cache so we don't have to reboot following an install. diff --git a/Clients/ExplorerPlugin/ExplorerPlugin.def b/Clients/ExplorerPlugin/ExplorerPlugin.def index e825180..acef773 100644 --- a/Clients/ExplorerPlugin/ExplorerPlugin.def +++ b/Clients/ExplorerPlugin/ExplorerPlugin.def @@ -1,28 +1,25 @@ ; +; ; Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved. ; -; @APPLE_LICENSE_HEADER_START@ +; Licensed under the Apache License, Version 2.0 (the "License"); +; you may not use this file except in compliance with the License. +; You may obtain a copy of the License at ; -; This file contains Original Code and/or Modifications of Original Code -; as defined in and that are subject to the Apple Public Source License -; Version 2.0 (the 'License'). You may not use this file except in -; compliance with the License. Please obtain a copy of the License at -; http://www.opensource.apple.com/apsl/ and read it before using this -; file. +; http://www.apache.org/licenses/LICENSE-2.0 ; -; The Original Code and all software distributed under the License are -; distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER -; EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, -; INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, -; FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. -; Please see the License for the specific language governing rights and +; Unless required by applicable law or agreed to in writing, software +; distributed under the License is distributed on an "AS IS" BASIS, +; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +; See the License for the specific language governing permissions and ; limitations under the License. -; -; @APPLE_LICENSE_HEADER_END@ ; ; Change History (most recent first): ; ; $Log: ExplorerPlugin.def,v $ +; Revision 1.3 2006/08/14 23:24:00 cheshire +; Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 +; ; Revision 1.2 2004/07/13 21:24:21 rpantos ; Fix for . ; diff --git a/Clients/ExplorerPlugin/ExplorerPlugin.h b/Clients/ExplorerPlugin/ExplorerPlugin.h index 40a709a..d14edd3 100644 --- a/Clients/ExplorerPlugin/ExplorerPlugin.h +++ b/Clients/ExplorerPlugin/ExplorerPlugin.h @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: ExplorerPlugin.h,v $ +Revision 1.4 2006/08/14 23:24:00 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.3 2005/01/25 18:35:38 shersche Declare APIs for obtaining handles to resource modules diff --git a/Clients/ExplorerPlugin/LoginDialog.cpp b/Clients/ExplorerPlugin/LoginDialog.cpp index ccee81c..c2afe22 100644 --- a/Clients/ExplorerPlugin/LoginDialog.cpp +++ b/Clients/ExplorerPlugin/LoginDialog.cpp @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: LoginDialog.cpp,v $ +Revision 1.3 2006/08/14 23:24:00 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.2 2004/07/13 21:24:21 rpantos Fix for . diff --git a/Clients/ExplorerPlugin/LoginDialog.h b/Clients/ExplorerPlugin/LoginDialog.h index a89c3a6..0f7bee6 100644 --- a/Clients/ExplorerPlugin/LoginDialog.h +++ b/Clients/ExplorerPlugin/LoginDialog.h @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: LoginDialog.h,v $ +Revision 1.3 2006/08/14 23:24:00 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.2 2004/07/13 21:24:21 rpantos Fix for . diff --git a/Clients/ExplorerPlugin/Resource.h b/Clients/ExplorerPlugin/Resource.h index e6a7b32..9b1f0ab 100644 --- a/Clients/ExplorerPlugin/Resource.h +++ b/Clients/ExplorerPlugin/Resource.h @@ -1,24 +1,18 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): diff --git a/Clients/ExplorerPlugin/StdAfx.cpp b/Clients/ExplorerPlugin/StdAfx.cpp index b97d864..1d64495 100644 --- a/Clients/ExplorerPlugin/StdAfx.cpp +++ b/Clients/ExplorerPlugin/StdAfx.cpp @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: StdAfx.cpp,v $ +Revision 1.3 2006/08/14 23:24:00 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.2 2004/07/13 21:24:21 rpantos Fix for . diff --git a/Clients/ExplorerPlugin/StdAfx.h b/Clients/ExplorerPlugin/StdAfx.h index 407ff3c..7976129 100644 --- a/Clients/ExplorerPlugin/StdAfx.h +++ b/Clients/ExplorerPlugin/StdAfx.h @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: StdAfx.h,v $ +Revision 1.4 2006/08/14 23:24:00 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.3 2005/10/19 19:50:34 herscher Workaround a bug in the latest Microsoft Platform SDK when compiling C++ files that include (directly or indirectly) diff --git a/Clients/Java/BrowserApp.java b/Clients/Java/BrowserApp.java index 0b55fa5..cbdd200 100644 --- a/Clients/Java/BrowserApp.java +++ b/Clients/Java/BrowserApp.java @@ -1,4 +1,5 @@ -/* +/* -*- Mode: Java; tab-width: 4 -*- + * * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. * * Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. diff --git a/Clients/Java/DNSSDUnitTest.java b/Clients/Java/DNSSDUnitTest.java index 786cab7..121ff61 100644 --- a/Clients/Java/DNSSDUnitTest.java +++ b/Clients/Java/DNSSDUnitTest.java @@ -1,28 +1,28 @@ -/* +/* -*- Mode: Java; tab-width: 4 -*- + * * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: DNSSDUnitTest.java,v $ +Revision 1.6 2006/08/14 23:24:07 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + +Revision 1.5 2006/06/20 23:01:58 rpantos + Java needs to implement DNSServiceRegisterRecord equivalent + Revision 1.4 2004/08/04 01:07:43 rpantos Update unit test for . @@ -107,6 +107,7 @@ class DNSSDUnitTest fRegTest = new RegTest(); new BrowseTest(); new DomainTest(); + new RegistrarTest(); this.waitForEnd(); } @@ -325,3 +326,30 @@ class QueryTest extends TermReporter implements QueryListener } } +class RegistrarTest extends TermReporter implements RegisterRecordListener +{ + public RegistrarTest() + { + try { + byte[] kResponsiblePerson = { 'g','r','o','v','e','r' }; + fRegistrar = DNSSD.createRecordRegistrar( this); + fRegistrar.registerRecord( DNSSD.UNIQUE, 0, + "test.registrartest.local", 17 /*ns_t_rp*/, 1, kResponsiblePerson, 3600); + } catch( Exception e) { e.printStackTrace(); } + } + + public void recordRegistered( DNSRecord record, int flags) + { + String s = "RegistrarTest result flags:" + String.valueOf( flags); + System.out.println( s); + + try { + byte[] kResponsiblePerson = { 'e','l','m','o' }; + record.update( 0, kResponsiblePerson, 3600); + record.remove(); + } catch( Exception e) { e.printStackTrace(); } + } + + protected DNSSDRecordRegistrar fRegistrar; +} + diff --git a/Clients/Java/SimpleChat.java b/Clients/Java/SimpleChat.java index 745b9a0..a1fee5c 100644 --- a/Clients/Java/SimpleChat.java +++ b/Clients/Java/SimpleChat.java @@ -1,4 +1,5 @@ -/* +/* -*- Mode: Java; tab-width: 4 -*- + * * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. * * Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. diff --git a/Clients/Java/SwingBrowseListener.java b/Clients/Java/SwingBrowseListener.java index 78bfe4f..db971b2 100644 --- a/Clients/Java/SwingBrowseListener.java +++ b/Clients/Java/SwingBrowseListener.java @@ -1,4 +1,5 @@ -/* +/* -*- Mode: Java; tab-width: 4 -*- + * * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. * * Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. diff --git a/Clients/Java/SwingDomainListener.java b/Clients/Java/SwingDomainListener.java index c6c380b..b67313b 100644 --- a/Clients/Java/SwingDomainListener.java +++ b/Clients/Java/SwingDomainListener.java @@ -1,4 +1,5 @@ -/* +/* -*- Mode: Java; tab-width: 4 -*- + * * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. * * Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. diff --git a/Clients/Java/SwingQueryListener.java b/Clients/Java/SwingQueryListener.java index 5f2de1d..fcac75b 100644 --- a/Clients/Java/SwingQueryListener.java +++ b/Clients/Java/SwingQueryListener.java @@ -1,4 +1,5 @@ -/* +/* -*- Mode: Java; tab-width: 4 -*- + * * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. * * Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. diff --git a/Clients/Java/SwingResolveListener.java b/Clients/Java/SwingResolveListener.java index f2be4b0..19c1799 100644 --- a/Clients/Java/SwingResolveListener.java +++ b/Clients/Java/SwingResolveListener.java @@ -1,4 +1,5 @@ -/* +/* -*- Mode: Java; tab-width: 4 -*- + * * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. * * Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. diff --git a/Clients/Java/nmakefile b/Clients/Java/nmakefile index 4c01633..9b08ccb 100644 --- a/Clients/Java/nmakefile +++ b/Clients/Java/nmakefile @@ -1,24 +1,18 @@ +# -*- tab-width: 4 -*- +# # Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved. # -# @APPLE_LICENSE_HEADER_START@ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at # -# This file contains Original Code and/or Modifications of Original Code -# as defined in and that are subject to the Apple Public Source License -# Version 2.0 (the 'License'). You may not use this file except in -# compliance with the License. Please obtain a copy of the License at -# http://www.opensource.apple.com/apsl/ and read it before using this -# file. +# http://www.apache.org/licenses/LICENSE-2.0 # -# The Original Code and all software distributed under the License are -# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER -# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, -# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. -# Please see the License for the specific language governing rights and +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and # limitations under the License. -# -# @APPLE_LICENSE_HEADER_END@ -# # # This Makefile builds .jar files for the DNS-SD Java sample apps. # You must have the Java support installed. diff --git a/Clients/Makefile b/Clients/Makefile index b79bf6f..c6c2ed2 100755 --- a/Clients/Makefile +++ b/Clients/Makefile @@ -1,25 +1,23 @@ +# -*- tab-width: 4 -*- +# # Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved. # -# @APPLE_LICENSE_HEADER_START@ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at # -# This file contains Original Code and/or Modifications of Original Code -# as defined in and that are subject to the Apple Public Source License -# Version 2.0 (the 'License'). You may not use this file except in -# compliance with the License. Please obtain a copy of the License at -# http://www.opensource.apple.com/apsl/ and read it before using this -# file. +# http://www.apache.org/licenses/LICENSE-2.0 # -# The Original Code and all software distributed under the License are -# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER -# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, -# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. -# Please see the License for the specific language governing rights and +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and # limitations under the License. -# -# @APPLE_LICENSE_HEADER_END@ # # $Log: Makefile,v $ +# Revision 1.8 2006/08/14 23:23:55 cheshire +# Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 +# # Revision 1.7 2006/01/06 01:06:17 cheshire # Compile library and client programs in one pass # diff --git a/Clients/PrinterSetupWizard/FirstPage.cpp b/Clients/PrinterSetupWizard/FirstPage.cpp index b5131da..8d4b881 100644 --- a/Clients/PrinterSetupWizard/FirstPage.cpp +++ b/Clients/PrinterSetupWizard/FirstPage.cpp @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 1997-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: FirstPage.cpp,v $ +Revision 1.6 2006/08/14 23:24:09 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.5 2005/07/07 17:53:20 shersche Fix problems associated with the CUPS printer workaround fix. diff --git a/Clients/PrinterSetupWizard/FirstPage.h b/Clients/PrinterSetupWizard/FirstPage.h index a798eb0..c7c96f4 100644 --- a/Clients/PrinterSetupWizard/FirstPage.h +++ b/Clients/PrinterSetupWizard/FirstPage.h @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 1997-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: FirstPage.h,v $ +Revision 1.3 2006/08/14 23:24:09 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.2 2005/07/07 17:53:20 shersche Fix problems associated with the CUPS printer workaround fix. diff --git a/Clients/PrinterSetupWizard/FourthPage.cpp b/Clients/PrinterSetupWizard/FourthPage.cpp index 876e28b..66e5145 100644 --- a/Clients/PrinterSetupWizard/FourthPage.cpp +++ b/Clients/PrinterSetupWizard/FourthPage.cpp @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 1997-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: FourthPage.cpp,v $ +Revision 1.8 2006/08/14 23:24:09 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.7 2005/07/07 17:53:20 shersche Fix problems associated with the CUPS printer workaround fix. diff --git a/Clients/PrinterSetupWizard/FourthPage.h b/Clients/PrinterSetupWizard/FourthPage.h index fca8cd1..fc72059 100644 --- a/Clients/PrinterSetupWizard/FourthPage.h +++ b/Clients/PrinterSetupWizard/FourthPage.h @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 1997-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: FourthPage.h,v $ +Revision 1.4 2006/08/14 23:24:09 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.3 2005/07/07 17:53:20 shersche Fix problems associated with the CUPS printer workaround fix. diff --git a/Clients/PrinterSetupWizard/PrinterSetupWizardApp.cpp b/Clients/PrinterSetupWizard/PrinterSetupWizardApp.cpp index 7b65443..e9e255f 100644 --- a/Clients/PrinterSetupWizard/PrinterSetupWizardApp.cpp +++ b/Clients/PrinterSetupWizard/PrinterSetupWizardApp.cpp @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 1997-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: PrinterSetupWizardApp.cpp,v $ +Revision 1.9 2006/08/14 23:24:09 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.8 2005/04/13 17:43:39 shersche Change "PrinterWizard.dll" to "PrinterWizardResources.dll" diff --git a/Clients/PrinterSetupWizard/PrinterSetupWizardApp.h b/Clients/PrinterSetupWizard/PrinterSetupWizardApp.h index 871de5d..08a1829 100644 --- a/Clients/PrinterSetupWizard/PrinterSetupWizardApp.h +++ b/Clients/PrinterSetupWizard/PrinterSetupWizardApp.h @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 1997-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: PrinterSetupWizardApp.h,v $ +Revision 1.3 2006/08/14 23:24:09 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.2 2005/01/25 08:52:55 shersche Add APIs to return localizable and non-localizable resource DLL handles Bug #: 3911084 diff --git a/Clients/PrinterSetupWizard/PrinterSetupWizardSheet.cpp b/Clients/PrinterSetupWizard/PrinterSetupWizardSheet.cpp index 6c0c9f3..e912716 100644 --- a/Clients/PrinterSetupWizard/PrinterSetupWizardSheet.cpp +++ b/Clients/PrinterSetupWizard/PrinterSetupWizardSheet.cpp @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 1997-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: PrinterSetupWizardSheet.cpp,v $ +Revision 1.35 2006/08/14 23:24:09 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.34 2005/10/05 17:32:51 herscher Use a case insensitive compare operation to check whether a printer with the same name has already been installed. diff --git a/Clients/PrinterSetupWizard/PrinterSetupWizardSheet.h b/Clients/PrinterSetupWizard/PrinterSetupWizardSheet.h index 63dc0c0..b9cc5ff 100644 --- a/Clients/PrinterSetupWizard/PrinterSetupWizardSheet.h +++ b/Clients/PrinterSetupWizard/PrinterSetupWizardSheet.h @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 1997-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: PrinterSetupWizardSheet.h,v $ +Revision 1.12 2006/08/14 23:24:09 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.11 2005/10/05 17:32:51 herscher Use a case insensitive compare operation to check whether a printer with the same name has already been installed. diff --git a/Clients/PrinterSetupWizard/SecondPage.cpp b/Clients/PrinterSetupWizard/SecondPage.cpp index c64030d..83e6685 100644 --- a/Clients/PrinterSetupWizard/SecondPage.cpp +++ b/Clients/PrinterSetupWizard/SecondPage.cpp @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 1997-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: SecondPage.cpp,v $ +Revision 1.19 2006/08/14 23:24:09 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.18 2005/07/20 17:44:54 shersche UI fixes for CUPS workaround diff --git a/Clients/PrinterSetupWizard/SecondPage.h b/Clients/PrinterSetupWizard/SecondPage.h index 5cf1852..b857334 100644 --- a/Clients/PrinterSetupWizard/SecondPage.h +++ b/Clients/PrinterSetupWizard/SecondPage.h @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 1997-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: SecondPage.h,v $ +Revision 1.9 2006/08/14 23:24:09 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.8 2005/03/20 20:08:37 shersche Second screen should not select a printer by default @@ -123,14 +120,22 @@ private: SetPrinterInformationState( BOOL state ); std::string m_selectedName; - -private: - - CStatic m_printerInformation; - CStatic m_descriptionLabel; - CStatic m_descriptionField; - CStatic m_locationLabel; - CStatic m_locationField; + + +private: + + + + CStatic m_printerInformation; + + CStatic m_descriptionLabel; + + CStatic m_descriptionField; + + CStatic m_locationLabel; + + CStatic m_locationField; + bool m_gotChoice; }; diff --git a/Clients/PrinterSetupWizard/ThirdPage.cpp b/Clients/PrinterSetupWizard/ThirdPage.cpp index bf16fe2..ac5ff1f 100644 --- a/Clients/PrinterSetupWizard/ThirdPage.cpp +++ b/Clients/PrinterSetupWizard/ThirdPage.cpp @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 1997-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: ThirdPage.cpp,v $ +Revision 1.28 2006/08/14 23:24:09 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.27 2005/10/05 21:41:45 herscher Use "application/octet-stream" to determine if CUPS shared queue supports raw diff --git a/Clients/PrinterSetupWizard/ThirdPage.h b/Clients/PrinterSetupWizard/ThirdPage.h index 8331421..b21f219 100644 --- a/Clients/PrinterSetupWizard/ThirdPage.h +++ b/Clients/PrinterSetupWizard/ThirdPage.h @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 1997-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: ThirdPage.h,v $ +Revision 1.6 2006/08/14 23:24:09 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.5 2005/07/07 17:53:20 shersche Fix problems associated with the CUPS printer workaround fix. diff --git a/Clients/PrinterSetupWizard/UtilTypes.h b/Clients/PrinterSetupWizard/UtilTypes.h index e5512b9..aad29f1 100644 --- a/Clients/PrinterSetupWizard/UtilTypes.h +++ b/Clients/PrinterSetupWizard/UtilTypes.h @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 1997-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: UtilTypes.h,v $ +Revision 1.15 2006/08/14 23:24:09 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.14 2005/06/30 18:02:54 shersche Workaround for Mac OS X Printer Sharing bug diff --git a/Clients/PrinterSetupWizard/resource.h b/Clients/PrinterSetupWizard/resource.h index 5d21d40..a44c06f 100644 --- a/Clients/PrinterSetupWizard/resource.h +++ b/Clients/PrinterSetupWizard/resource.h @@ -1,24 +1,18 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 1997-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): diff --git a/Clients/PrinterSetupWizard/stdafx.cpp b/Clients/PrinterSetupWizard/stdafx.cpp index 53abf25..548f66f 100644 --- a/Clients/PrinterSetupWizard/stdafx.cpp +++ b/Clients/PrinterSetupWizard/stdafx.cpp @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 1997-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: stdafx.cpp,v $ +Revision 1.2 2006/08/14 23:24:09 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.1 2004/06/18 04:36:58 rpantos First checked in diff --git a/Clients/PrinterSetupWizard/stdafx.h b/Clients/PrinterSetupWizard/stdafx.h index 8ec4bdb..e1ecec8 100644 --- a/Clients/PrinterSetupWizard/stdafx.h +++ b/Clients/PrinterSetupWizard/stdafx.h @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 1997-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: stdafx.h,v $ +Revision 1.3 2006/08/14 23:24:09 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.2 2005/10/19 19:50:35 herscher Workaround a bug in the latest Microsoft Platform SDK when compiling C++ files that include (directly or indirectly) diff --git a/Clients/SimpleChat.NET/AssemblyInfo.cs b/Clients/SimpleChat.NET/AssemblyInfo.cs index a778420..4fc7745 100755 --- a/Clients/SimpleChat.NET/AssemblyInfo.cs +++ b/Clients/SimpleChat.NET/AssemblyInfo.cs @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 1997-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: AssemblyInfo.cs,v $ +Revision 1.2 2006/08/14 23:24:21 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.1 2004/07/19 07:57:08 shersche Initial revision diff --git a/Clients/SimpleChat.NET/SimpleChat.cs b/Clients/SimpleChat.NET/SimpleChat.cs index fb841f2..e7f3b1e 100755 --- a/Clients/SimpleChat.NET/SimpleChat.cs +++ b/Clients/SimpleChat.NET/SimpleChat.cs @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 1997-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: SimpleChat.cs,v $ +Revision 1.6 2006/08/14 23:24:21 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.5 2004/09/13 19:37:42 shersche Change code to reflect namespace and type changes to dnssd.NET library diff --git a/Clients/dns-sd.c b/Clients/dns-sd.c index 34af2d6..31e620d 100644 --- a/Clients/dns-sd.c +++ b/Clients/dns-sd.c @@ -1,5 +1,6 @@ -/* - * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. +/* -*- Mode: C; tab-width: 4 -*- + * + * Copyright (c) 2002-2006 Apple Computer, Inc. All rights reserved. * * Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. * ("Apple") in consideration of your agreement to the following terms, and your @@ -62,6 +63,9 @@ cl dns-sd.c -I../mDNSShared -DNOT_HAVE_GETOPT ws2_32.lib ..\mDNSWindows\DLL\Rele (may require that you run a Visual Studio script such as vsvars32.bat first) */ +// For testing changes to dnssd_clientstub.c, uncomment this line and the #include below +// #define __APPLE_API_PRIVATE 1 + #include "dns_sd.h" #include #include // For stdout, stderr @@ -79,15 +83,18 @@ typedef int pid_t; #define getpid _getpid #define strcasecmp _stricmp #define snprintf _snprintf +static const char kFilePathSep = '\\'; #else #include // For getopt() and optind #include // For getaddrinfo() #include // For struct timeval -#include // For inet_addr() -#include // For struct sockaddr_in() #include // For AF_INET +#include // For struct sockaddr_in() +#include // For inet_addr() +static const char kFilePathSep = '/'; #endif +//#include "../mDNSShared/dnssd_clientstub.c" //************************************************************************************************************* // Globals @@ -104,7 +111,7 @@ static DNSRecordRef record = NULL; static char myhinfoW[14] = "\002PC\012Windows XP"; static char myhinfoX[ 9] = "\003Mac\004OS X"; static char updatetest[3] = "\002AA"; -static char bigNULL[4096]; +static char bigNULL[8200]; // Note: the select() implementation on Windows (Winsock2) fails with any timeout much larger than this #define LONG_TIME 100000000 @@ -229,48 +236,52 @@ static void DNSSD_API enum_reply(DNSServiceRef client, const DNSServiceFlags fla (void)client; // Unused (void)ifIndex; // Unused - (void)errorCode; // Unused (void)context; // Unused - - if (!*replyDomain) return; // 1. Print the header if (num_printed++ == 0) printf("Timestamp Recommended %s domain\n", operation == 'E' ? "Registration" : "Browsing"); printtimestamp(); - printf("%-10s", DomainMsg(flags)); - printf("%-8s", (flags & kDNSServiceFlagsMoreComing) ? "(More)" : ""); - if (partialflags) printf("Flags: %4X ", partialflags); - else printf(" "); - - // 2. Count the labels - while (*replyDomain) + if (errorCode) + printf("Error code %d\n", errorCode); + else if (!*replyDomain) + printf("Error: No reply domain\n"); + else { - label[labels++] = replyDomain; - replyDomain = GetNextLabel(replyDomain, text); - } + printf("%-10s", DomainMsg(flags)); + printf("%-8s", (flags & kDNSServiceFlagsMoreComing) ? "(More)" : ""); + if (partialflags) printf("Flags: %4X ", partialflags); + else printf(" "); + + // 2. Count the labels + while (*replyDomain) + { + label[labels++] = replyDomain; + replyDomain = GetNextLabel(replyDomain, text); + } + + // 3. Decide if we're going to clump the last two or three labels (e.g. "apple.com", or "nicta.com.au") + if (labels >= 3 && replyDomain - label[labels-1] <= 3 && label[labels-1] - label[labels-2] <= 4) initial = 3; + else if (labels >= 2 && replyDomain - label[labels-1] <= 4) initial = 2; + else initial = 1; + labels -= initial; - // 3. Decide if we're going to clump the last two or three labels (e.g. "apple.com", or "nicta.com.au") - if (labels >= 3 && replyDomain - label[labels-1] <= 3 && label[labels-1] - label[labels-2] <= 4) initial = 3; - else if (labels >= 2 && replyDomain - label[labels-1] <= 4) initial = 2; - else initial = 1; - labels -= initial; - - // 4. Print the initial one-, two- or three-label clump - for (i=0; i0) printf("."); - printf("%s", text); - } - printf("\n"); - - // 5. Print the remainder of the hierarchy - for (depth=0; depth %s\n", text); + // 4. Print the initial one-, two- or three-label clump + for (i=0; i0) printf("."); + printf("%s", text); + } + printf("\n"); + + // 5. Print the remainder of the hierarchy + for (depth=0; depth %s\n", text); + } } if (!(flags & kDNSServiceFlagsMoreComing)) fflush(stdout); @@ -281,50 +292,69 @@ static void DNSSD_API browse_reply(DNSServiceRef client, const DNSServiceFlags f { char *op = (flags & kDNSServiceFlagsAdd) ? "Add" : "Rmv"; (void)client; // Unused - (void)errorCode; // Unused (void)context; // Unused if (num_printed++ == 0) printf("Timestamp A/R Flags if %-25s %-25s %s\n", "Domain", "Service Type", "Instance Name"); printtimestamp(); - printf("%s%6X%3d %-25s %-25s %s\n", op, flags, ifIndex, replyDomain, replyType, replyName); + if (errorCode) printf("Error code %d\n", errorCode); + else printf("%s%6X%3d %-25s %-25s %s\n", op, flags, ifIndex, replyDomain, replyType, replyName); if (!(flags & kDNSServiceFlagsMoreComing)) fflush(stdout); } +static void ShowTXTRecord(uint16_t txtLen, const unsigned char *txtRecord) + { + const unsigned char *ptr = txtRecord; + const unsigned char *max = txtRecord + txtLen; + while (ptr < max) + { + const unsigned char *const end = ptr + 1 + ptr[0]; + if (end > max) { printf("<< invalid data >>"); break; } + if (++ptr < end) printf(" "); // As long as string is non-empty, begin with a space + while (ptr^()[]{}$", *ptr)) printf("\\"); + if (*ptr == '\\') printf("\\\\\\\\"); + else if (*ptr >= ' ' ) printf("%c", *ptr); + else printf("\\\\x%02X", *ptr); + ptr++; + } + } + } + static void DNSSD_API resolve_reply(DNSServiceRef client, const DNSServiceFlags flags, uint32_t ifIndex, DNSServiceErrorType errorCode, - const char *fullname, const char *hosttarget, uint16_t opaqueport, uint16_t txtLen, const char *txtRecord, void *context) + const char *fullname, const char *hosttarget, uint16_t opaqueport, uint16_t txtLen, const unsigned char *txtRecord, void *context) { union { uint16_t s; u_char b[2]; } port = { opaqueport }; uint16_t PortAsNumber = ((uint16_t)port.b[0]) << 8 | port.b[1]; (void)client; // Unused (void)ifIndex; // Unused - (void)errorCode; // Unused (void)context; // Unused printtimestamp(); - printf("%s can be reached at %s:%u", fullname, hosttarget, PortAsNumber); - - if (flags) printf(" Flags: %X", flags); - if (txtLen > 1) // Don't show degenerate TXT records containing nothing but a single empty string + if (errorCode) printf("Error code %d\n", errorCode); + else { - const char *ptr = txtRecord; - const char *max = txtRecord + txtLen; - printf(" TXT"); - while (ptr < max) - { - const char *end = ptr + 1 + ptr[0]; - if (end > max) { printf("<< invalid data >>"); break; } - if (++ptr < end) printf(" "); // As long as string is non-empty, begin with a space - while (ptr < end) - { - if (*ptr == '\\') printf("\\\\"); // '\' displays as "\\" - else if (*ptr == ' ' ) printf("\\ "); // ' ' displays as "\ " - else if (*ptr > ' ' ) printf("%c", *ptr); // Display normal characters as-is - else printf("\\x%02X", *ptr); // ther chararacters displayed as "\xHH" - ptr++; - } - } + printf("%s can be reached at %s:%u", fullname, hosttarget, PortAsNumber); + if (flags) printf(" Flags: %X", flags); + // Don't show degenerate TXT records containing nothing but a single empty string + if (txtLen > 1) { printf("\n"); ShowTXTRecord(txtLen, txtRecord); } + printf("\n"); } - printf("\n"); + if (!(flags & kDNSServiceFlagsMoreComing)) fflush(stdout); } @@ -389,14 +419,20 @@ static void DNSSD_API reg_reply(DNSServiceRef client, const DNSServiceFlags flag (void)context; // Unused printf("Got a reply for %s.%s%s: ", name, regtype, domain); - switch (errorCode) + + if (errorCode == kDNSServiceErr_NoError) { - case kDNSServiceErr_NoError: printf("Name now registered and active\n"); break; - case kDNSServiceErr_NameConflict: printf("Name in use, please choose another\n"); exit(-1); - default: printf("Error %d\n", errorCode); return; + printf("Name now registered and active\n"); + if (operation == 'A' || operation == 'U' || operation == 'N') timeOut = 5; } + else if (errorCode == kDNSServiceErr_NameConflict) + { + printf("Name in use, please choose another\n"); + exit(-1); + } + else + printf("Error %d\n", errorCode); - if (operation == 'A' || operation == 'U' || operation == 'N') timeOut = 5; if (!(flags & kDNSServiceFlagsMoreComing)) fflush(stdout); } @@ -407,26 +443,39 @@ static void DNSSD_API qr_reply(DNSServiceRef sdRef, const DNSServiceFlags flags, const unsigned char *rd = rdata; const unsigned char *end = (const unsigned char *) rdata + rdlen; char rdb[1000]; - char *p = rdb; - const char * const lim = rdb + sizeof(rdb); + int unknowntype = 0; (void)sdRef; // Unused (void)flags; // Unused (void)ifIndex; // Unused - (void)errorCode;// Unused (void)ttl; // Unused (void)context; // Unused - switch (rrtype) - { - case kDNSServiceType_A: sprintf(rdb, "%d.%d.%d.%d", rd[0], rd[1], rd[2], rd[3]); break; - default : p += snprintf(p, lim-p, "%d bytes%s", rdlen, rdlen ? ":" : ""); - while (rd < end && p < lim) p += snprintf(p, lim-p, " %02X", *rd++); - break; - } if (num_printed++ == 0) printf("Timestamp A/R Flags if %-30s%4s%4s Rdata\n", "Name", "T", "C"); printtimestamp(); - printf("%s%6X%3d %-30s%4d%4d %s\n", op, flags, ifIndex, fullname, rrtype, rrclass, rdb); + if (errorCode) + printf("Error code %d\n", errorCode); + else + { + switch (rrtype) + { + case kDNSServiceType_A: sprintf(rdb, "%d.%d.%d.%d", rd[0], rd[1], rd[2], rd[3]); break; + case kDNSServiceType_AAAA: sprintf(rdb, "%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X", + rd[0x0], rd[0x1], rd[0x2], rd[0x3], rd[0x4], rd[0x5], rd[0x6], rd[0x7], + rd[0x8], rd[0x9], rd[0xA], rd[0xB], rd[0xC], rd[0xD], rd[0xE], rd[0xF]); break; + break; + default : sprintf(rdb, "%d bytes%s", rdlen, rdlen ? ":" : ""); unknowntype = 1; break; + } + + printf("%s%6X%3d %-30s%4d%4d %s", op, flags, ifIndex, fullname, rrtype, rrclass, rdb); + if (unknowntype) while (rd < end) printf(" %02X", *rd++); + printf("\n"); + + if (operation == 'C') + if (flags & kDNSServiceFlagsAdd) + DNSServiceReconfirmRecord(flags, ifIndex, fullname, rrtype, rrclass, rdlen, rdata); + } + if (!(flags & kDNSServiceFlagsMoreComing)) fflush(stdout); } @@ -456,7 +505,7 @@ static void HandleEvents(void) if (client2) FD_SET(dns_sd_fd2, &readfds); // 3. Set up the timeout. - tv.tv_sec = timeOut; + tv.tv_sec = timeOut; tv.tv_usec = 0; result = select(nfds, &readfds, (fd_set*)NULL, (fd_set*)NULL, &tv); @@ -481,7 +530,7 @@ static int getfirstoption( int argc, char **argv, const char *optstr, int *pOptI // Return the recognized option in optstr and the option index of the next arg. #if NOT_HAVE_GETOPT { - int i; + int i; for ( i=1; i < argc; i++) { if ( argv[i][0] == '-' && &argv[i][1] && @@ -495,7 +544,7 @@ static int getfirstoption( int argc, char **argv, const char *optstr, int *pOptI } #else { - int operation = getopt(argc, (char * const *)argv, optstr); + int operation = getopt(argc, (char * const *)argv, optstr); *pOptInd = optind; return operation; } @@ -515,7 +564,7 @@ static void DNSSD_API MyRegisterRecordCallback(DNSServiceRef service, DNSRecordR { case kDNSServiceErr_NoError: printf("Name now registered and active\n"); break; case kDNSServiceErr_NameConflict: printf("Name in use, please choose another\n"); exit(-1); - default: printf("Error %d\n", errorCode); return; + default: printf("Error %d\n", errorCode); break; } if (!(flags & kDNSServiceFlagsMoreComing)) fflush(stdout); } @@ -544,9 +593,10 @@ static unsigned long getip(const char *const name) static DNSServiceErrorType RegisterProxyAddressRecord(DNSServiceRef *sdRef, const char *host, const char *ip) { - // Call getip() after the call DNSServiceCreateConnection(). On the Win32 platform, WinSock must - // be initialized for getip() to succeed. Any DNSService* call will initialize WinSock for us, - // so make sure DNSServiceCreateConnection() is called before getip() is. + // Call getip() after the call DNSServiceCreateConnection(). + // On the Win32 platform, WinSock must be initialized for getip() to succeed. + // Any DNSService* call will initialize WinSock for us, so we make sure + // DNSServiceCreateConnection() is called before getip() is. unsigned long addr = 0; DNSServiceErrorType err = DNSServiceCreateConnection(sdRef); if (err) { fprintf(stderr, "DNSServiceCreateConnection returned %d\n", err); return(err); } @@ -556,6 +606,12 @@ static DNSServiceErrorType RegisterProxyAddressRecord(DNSServiceRef *sdRef, cons // Note, should probably add support for creating proxy AAAA records too, one day } +#define HexVal(X) ( ((X) >= '0' && (X) <= '9') ? ((X) - '0' ) : \ + ((X) >= 'A' && (X) <= 'F') ? ((X) - 'A' + 10) : \ + ((X) >= 'a' && (X) <= 'f') ? ((X) - 'a' + 10) : 0) + +#define HexPair(P) ((HexVal((P)[0]) << 4) | HexVal((P)[1])) + static DNSServiceErrorType RegisterService(DNSServiceRef *sdRef, const char *nam, const char *typ, const char *dom, const char *host, const char *port, int argc, char **argv) { @@ -572,16 +628,22 @@ static DNSServiceErrorType RegisterService(DNSServiceRef *sdRef, if (host && *host) printf(" host %s", host); printf(" port %s\n", port); - for (i = 0; i < argc; i++) + if (argc) { - int length = strlen(argv[i]); - if (length <= 255) + for (i = 0; i < argc; i++) { - *ptr++ = (unsigned char)length; - strcpy((char*)ptr, argv[i]); - ptr += length; - printf("TXT %s\n", argv[i]); + const char *p = argv[i]; + *ptr = 0; + while (*p && *ptr < 255 && ptr + 1 + *ptr < txt+sizeof(txt)) + { + if (p[0] != '\\' || p[1] == 0) { ptr[++*ptr] = *p; p+=1; } + else if (p[1] == 'x' && isxdigit(p[2]) && isxdigit(p[3])) { ptr[++*ptr] = HexPair(p+2); p+=4; } + else { ptr[++*ptr] = p[1]; p+=2; } + } + ptr += 1 + *ptr; } + ShowTXTRecord(ptr-txt, txt); + printf("\n"); } return(DNSServiceRegister(sdRef, /* kDNSServiceFlagsAllowRemoteQuery */ 0, opinterface, nam, typ, dom, host, registerPort.NotAnInteger, (uint16_t) (ptr-txt), txt, reg_reply, NULL)); @@ -589,15 +651,15 @@ static DNSServiceErrorType RegisterService(DNSServiceRef *sdRef, int main(int argc, char **argv) { -#ifdef _WIN32 - const char kFilePathSep = '\\'; -#else - const char kFilePathSep = '/'; -#endif DNSServiceErrorType err; char *dom; - int optind; - const char *progname = strrchr(argv[0], kFilePathSep) ? strrchr(argv[0], kFilePathSep) + 1 : argv[0]; + int optind; + + // Extract the program name from argv[0], which by convention contains the path to this executable. + // Note that this is just a voluntary convention, not enforced by the kernel -- + // the process calling exec() can pass bogus data in argv[0] if it chooses to. + const char *a0 = strrchr(argv[0], kFilePathSep) + 1; + if (a0 == (const char *)1) a0 = argv[0]; if (argc > 1 && !strcmp(argv[1], "-lo")) { @@ -616,7 +678,7 @@ int main(int argc, char **argv) } if (argc < 2) goto Fail; // Minimum command line is the command name and one argument - operation = getfirstoption( argc, argv, "EFBLQRPAUNTMI", &optind); + operation = getfirstoption( argc, argv, "EFBLRPQCAUNTMI", &optind); if (operation == -1) goto Fail; switch (operation) @@ -644,7 +706,7 @@ int main(int argc, char **argv) dom = (argc < optind+3) ? "local" : argv[optind+2]; if (dom[0] == '.' && dom[1] == 0) dom = "local"; // We allow '.' on the command line as a synonym for "local" printf("Lookup %s.%s.%s\n", argv[optind+0], argv[optind+1], dom); - err = DNSServiceResolve(&client, 0, opinterface, argv[optind+0], argv[optind+1], dom, resolve_reply, NULL); + err = DNSServiceResolve(&client, 0, opinterface, argv[optind+0], argv[optind+1], dom, (DNSServiceResolveReply)resolve_reply, NULL); break; case 'R': if (argc < optind+4) goto Fail; @@ -657,9 +719,10 @@ int main(int argc, char **argv) err = RegisterService(&client, argv[optind+0], argv[optind+1], argv[optind+2], argv[optind+4], argv[optind+3], argc-(optind+6), argv+(optind+6)); break; - case 'Q': { + case 'Q': + case 'C': { uint16_t rrtype, rrclass; - DNSServiceFlags flags = 0; + DNSServiceFlags flags = kDNSServiceFlagsReturnCNAME; if (argc < optind+1) goto Fail; rrtype = (argc <= optind+1) ? kDNSServiceType_A : GetRRType(argv[optind+1]); rrclass = (argc <= optind+2) ? kDNSServiceClass_IN : atoi(argv[optind+2]); @@ -722,18 +785,19 @@ int main(int argc, char **argv) return 0; Fail: - fprintf(stderr, "%s -E (Enumerate recommended registration domains)\n", progname); - fprintf(stderr, "%s -F (Enumerate recommended browsing domains)\n", progname); - fprintf(stderr, "%s -B (Browse for services instances)\n", progname); - fprintf(stderr, "%s -L (Look up a service instance)\n", progname); - fprintf(stderr, "%s -R [...] (Register a service)\n", progname); - fprintf(stderr, "%s -P [...] (Proxy)\n", progname); - fprintf(stderr, "%s -Q (Generic query for any record type)\n", progname); - fprintf(stderr, "%s -A (Test Adding/Updating/Deleting a record)\n", progname); - fprintf(stderr, "%s -U (Test updating a TXT record)\n", progname); - fprintf(stderr, "%s -N (Test adding a large NULL record)\n", progname); - fprintf(stderr, "%s -T (Test creating a large TXT record)\n", progname); - fprintf(stderr, "%s -M (Test creating a registration with multiple TXT records)\n", progname); - fprintf(stderr, "%s -I (Test registering and then immediately updating TXT record)\n", progname); + fprintf(stderr, "%s -E (Enumerate recommended registration domains)\n", a0); + fprintf(stderr, "%s -F (Enumerate recommended browsing domains)\n", a0); + fprintf(stderr, "%s -B (Browse for services instances)\n", a0); + fprintf(stderr, "%s -L (Look up a service instance)\n", a0); + fprintf(stderr, "%s -R [...] (Register a service)\n", a0); + fprintf(stderr, "%s -P [...] (Proxy)\n", a0); + fprintf(stderr, "%s -Q (Generic query for any record type)\n", a0); + fprintf(stderr, "%s -C (Query; reconfirming each result)\n", a0); + fprintf(stderr, "%s -A (Test Adding/Updating/Deleting a record)\n", a0); + fprintf(stderr, "%s -U (Test updating a TXT record)\n", a0); + fprintf(stderr, "%s -N (Test adding a large NULL record)\n", a0); + fprintf(stderr, "%s -T (Test creating a large TXT record)\n", a0); + fprintf(stderr, "%s -M (Test creating a registration with multiple TXT records)\n", a0); + fprintf(stderr, "%s -I (Test registering and then immediately updating TXT record)\n", a0); return 0; } diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f458904 --- /dev/null +++ b/LICENSE @@ -0,0 +1,13 @@ +The majority of the source code in the mDNSResponder project is licensed +under the terms of the Apache License, Version 2.0, available from: + + +To accommodate license compatibility with the widest possible range +of client code licenses, the shared library code, which is linked +at runtime into the same address space as the client using it, is +licensed under the terms of the "Three-Clause BSD License". + +The Linux Name Service Switch code, contributed by National ICT +Australia Ltd (NICTA) is licensed under the terms of the NICTA Public +Software Licence (which is substantially similar to the "Three-Clause +BSD License", with some additional language pertaining to Australian law). diff --git a/Makefile b/Makefile index e4a7574..61219d3 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ include /Developer/Makefiles/pb_makefiles/platform.make -MVERS = "mDNSResponder-107.5" +MVERS = "mDNSResponder-107.6" install: cd "$(SRCROOT)/mDNSMacOSX"; xcodebuild install OBJROOT=$(OBJROOT) SYMROOT=$(SYMROOT) DSTROOT=$(DSTROOT) MVERS=$(MVERS) diff --git a/mDNSCore/DNSCommon.c b/mDNSCore/DNSCommon.c index a1b7dc4..08507b0 100644 --- a/mDNSCore/DNSCommon.c +++ b/mDNSCore/DNSCommon.c @@ -2,28 +2,51 @@ * * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: DNSCommon.c,v $ +Revision 1.100.2.1 2006/08/29 06:24:22 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + +Revision 1.100 2006/06/08 22:58:46 cheshire + IPv6 link-local address prefix is FE80::/10, not FE80::/16 + +Revision 1.99 2006/05/18 01:32:33 cheshire + iChat: Lost connection with Bonjour +(mDNSResponder insufficiently defensive against malformed browsing PTR responses) + +Revision 1.98 2006/03/19 17:00:58 cheshire +Define symbol MaxMsg instead of using hard-coded constant value '80' + +Revision 1.97 2006/03/18 21:47:56 cheshire + Improve logic for delaying packets after repeated interface transitions + +Revision 1.96 2006/03/10 21:51:42 cheshire + After record update, old record sometimes remains in cache +Split out SameRDataBody() into a separate routine so it can be called from other code + +Revision 1.95 2006/03/08 22:43:11 cheshire +Use "localdomain" symbol instead of literal string + +Revision 1.94 2006/03/02 21:59:55 cheshire + Spurious warning "GetLargeResourceRecord: m->rec appears to be already in use" +Improve sanity checks & debugging support in GetLargeResourceRecord() + +Revision 1.93 2006/03/02 20:30:47 cheshire +Improved GetRRDisplayString to also show priority, weight, and port for SRV records + Revision 1.92 2005/09/16 21:06:49 cheshire Use mDNS_TimeNow_NoLock macro, instead of writing "mDNSPlatformRawTime() + m->timenow_adjust" all over the place @@ -445,22 +468,24 @@ mDNSexport char *DNSTypeName(mDNSu16 rrtype) // long as this routine is only used for debugging messages, it probably isn't a big problem. mDNSexport char *GetRRDisplayString_rdb(const ResourceRecord *rr, RDataBody *rd, char *buffer) { + #define Max (MaxMsg-1) char *ptr = buffer; - mDNSu32 length = mDNS_snprintf(buffer, 79, "%4d %##s %s ", rr->rdlength, rr->name->c, DNSTypeName(rr->rrtype)); + mDNSu32 length = mDNS_snprintf(buffer, Max, "%4d %##s %s ", rr->rdlength, rr->name->c, DNSTypeName(rr->rrtype)); switch (rr->rrtype) { - case kDNSType_A: mDNS_snprintf(buffer+length, 79-length, "%.4a", &rd->ipv4); break; + case kDNSType_A: mDNS_snprintf(buffer+length, Max-length, "%.4a", &rd->ipv4); break; case kDNSType_NS: // Same as PTR case kDNSType_CNAME:// Same as PTR - case kDNSType_PTR: mDNS_snprintf(buffer+length, 79-length, "%##s", rd->name.c); break; + case kDNSType_PTR: mDNS_snprintf(buffer+length, Max-length, "%##s", rd->name.c); break; case kDNSType_HINFO:// Display this the same as TXT (just show first string) - case kDNSType_TXT: mDNS_snprintf(buffer+length, 79-length, "%#s", rd->txt.c); break; + case kDNSType_TXT: mDNS_snprintf(buffer+length, Max-length, "%#s", rd->txt.c); break; - case kDNSType_AAAA: mDNS_snprintf(buffer+length, 79-length, "%.16a", &rd->ipv6); break; - case kDNSType_SRV: mDNS_snprintf(buffer+length, 79-length, "%##s", rd->srv.target.c); break; - default: mDNS_snprintf(buffer+length, 79-length, "RDLen %d: %s", rr->rdlength, rd->data); break; + case kDNSType_AAAA: mDNS_snprintf(buffer+length, Max-length, "%.16a", &rd->ipv6); break; + case kDNSType_SRV: mDNS_snprintf(buffer+length, Max-length, "%u %u %u %##s", + rd->srv.priority, rd->srv.weight, mDNSVal16(rd->srv.port), rd->srv.target.c); break; + default: mDNS_snprintf(buffer+length, Max-length, "RDLen %d: %s", rr->rdlength, rd->data); break; } for (ptr = buffer; *ptr; ptr++) if (*ptr < ' ') *ptr='.'; return(buffer); @@ -482,6 +507,14 @@ mDNSexport mDNSu32 mDNSRandom(mDNSu32 max) return (seed & mask); } +mDNSexport mDNSu32 mDNSRandomFromFixedSeed(mDNSu32 seed, mDNSu32 max) + { + mDNSu32 mask = 1; + while (mask < max) mask = (mask << 1) | 1; + do seed = seed * 21 + 1; while ((seed & mask) > max); + return (seed & mask); + } + mDNSexport mDNSBool mDNSSameAddress(const mDNSAddr *ip1, const mDNSAddr *ip2) { if (ip1->type == ip2->type) @@ -556,10 +589,13 @@ mDNSexport mDNSBool SameDomainName(const domainname *const d1, const domainname mDNSexport mDNSBool IsLocalDomain(const domainname *d) { // Domains that are defined to be resolved via link-local multicast are: - // local., 254.169.in-addr.arpa., and 0.8.E.F.ip6.arpa. - static const domainname *n0 = (domainname*)"\x5" "local"; - static const domainname *n1 = (domainname*)"\x3" "254" "\x3" "169" "\x7" "in-addr" "\x4" "arpa"; - static const domainname *n2 = (domainname*)"\x1" "0" "\x1" "8" "\x1" "e" "\x1" "f" "\x3" "ip6" "\x4" "arpa"; + // local., 254.169.in-addr.arpa., and {8,9,A,B}.E.F.ip6.arpa. + static const domainname *nL = (domainname*)"\x5" "local"; + static const domainname *nR = (domainname*)"\x3" "254" "\x3" "169" "\x7" "in-addr" "\x4" "arpa"; + static const domainname *n8 = (domainname*)"\x1" "8" "\x1" "e" "\x1" "f" "\x3" "ip6" "\x4" "arpa"; + static const domainname *n9 = (domainname*)"\x1" "9" "\x1" "e" "\x1" "f" "\x3" "ip6" "\x4" "arpa"; + static const domainname *nA = (domainname*)"\x1" "a" "\x1" "e" "\x1" "f" "\x3" "ip6" "\x4" "arpa"; + static const domainname *nB = (domainname*)"\x1" "b" "\x1" "e" "\x1" "f" "\x3" "ip6" "\x4" "arpa"; const domainname *d1, *d2, *d3, *d4, *d5, *d6; // Top-level domain, second-level domain, etc. d1 = d2 = d3 = d4 = d5 = d6 = mDNSNULL; @@ -569,9 +605,12 @@ mDNSexport mDNSBool IsLocalDomain(const domainname *d) d = (domainname*)(d->c + 1 + d->c[0]); } - if (d1 && SameDomainName(d1, n0)) return(mDNStrue); - if (d4 && SameDomainName(d4, n1)) return(mDNStrue); - if (d6 && SameDomainName(d6, n2)) return(mDNStrue); + if (d1 && SameDomainName(d1, nL)) return(mDNStrue); + if (d4 && SameDomainName(d4, nR)) return(mDNStrue); + if (d6 && SameDomainName(d6, n8)) return(mDNStrue); + if (d6 && SameDomainName(d6, n9)) return(mDNStrue); + if (d6 && SameDomainName(d6, nA)) return(mDNStrue); + if (d6 && SameDomainName(d6, nB)) return(mDNStrue); return(mDNSfalse); } @@ -872,7 +911,7 @@ mDNSexport mDNSu8 *ConstructServiceName(domainname *const fqdn, src = type->c; // Put the service type into the domain name len = *src; - if (len < 2 || len >= 0x40 || (len > 15 && !SameDomainName(domain, (domainname*)"\x05" "local"))) + if (len < 2 || len >= 0x40 || (len > 15 && !SameDomainName(domain, &localdomain))) { errormsg="Application protocol name must be underscore plus 1-14 characters. See "; goto fail; @@ -905,6 +944,11 @@ fail: return(mDNSNULL); } +// A service name has the form: instance.application-protocol.transport-protocol.domain +// DeconstructServiceName is currently fairly forgiving: It doesn't try to enforce character +// set or length limits for the protocol names, and the final domain is allowed to be empty. +// However, if the given FQDN doesn't contain at least three labels, +// DeconstructServiceName will reject it and return mDNSfalse. mDNSexport mDNSBool DeconstructServiceName(const domainname *const fqdn, domainlabel *const name, domainname *const type, domainname *const domain) { @@ -913,29 +957,32 @@ mDNSexport mDNSBool DeconstructServiceName(const domainname *const fqdn, const mDNSu8 *max = fqdn->c + MAX_DOMAIN_NAME; mDNSu8 *dst; - dst = name->c; // Extract the service name from the domain name + dst = name->c; // Extract the service name len = *src; - if (len >= 0x40) { debugf("DeconstructServiceName: service name too long"); return(mDNSfalse); } + if (!len) { debugf("DeconstructServiceName: FQDN empty!"); return(mDNSfalse); } + if (len >= 0x40) { debugf("DeconstructServiceName: Instance name too long"); return(mDNSfalse); } for (i=0; i<=len; i++) *dst++ = *src++; - dst = type->c; // Extract the service type from the domain name + dst = type->c; // Extract the service type len = *src; - if (len >= 0x40) { debugf("DeconstructServiceName: service type too long"); return(mDNSfalse); } + if (!len) { debugf("DeconstructServiceName: FQDN contains only one label!"); return(mDNSfalse); } + if (len >= 0x40) { debugf("DeconstructServiceName: Application protocol name too long"); return(mDNSfalse); } for (i=0; i<=len; i++) *dst++ = *src++; len = *src; - if (len >= 0x40) { debugf("DeconstructServiceName: service type too long"); return(mDNSfalse); } + if (!len) { debugf("DeconstructServiceName: FQDN contains only two labels!"); return(mDNSfalse); } + if (len >= 0x40) { debugf("DeconstructServiceName: Transport protocol name too long"); return(mDNSfalse); } for (i=0; i<=len; i++) *dst++ = *src++; - *dst++ = 0; // Put the null root label on the end of the service type + *dst++ = 0; // Put terminator on the end of service type - dst = domain->c; // Extract the service domain from the domain name + dst = domain->c; // Extract the service domain while (*src) { len = *src; if (len >= 0x40) - { debugf("DeconstructServiceName: service domain label too long"); return(mDNSfalse); } + { debugf("DeconstructServiceName: Label in service domain too long"); return(mDNSfalse); } if (src + 1 + len + 1 >= max) - { debugf("DeconstructServiceName: service domain too long"); return(mDNSfalse); } + { debugf("DeconstructServiceName: Total service domain too long"); return(mDNSfalse); } for (i=0; i<=len; i++) *dst++ = *src++; } *dst++ = 0; // Put the null root label on the end @@ -1101,25 +1148,32 @@ mDNSexport mDNSu32 RDataHashValue(mDNSu16 const rdlength, const RDataBody *const return(sum); } -mDNSexport mDNSBool SameRData(const ResourceRecord *const r1, const ResourceRecord *const r2) +// r1 has to be a full ResourceRecord including rrtype and rdlength +// r2 is just a bare RDataBody, which MUST be the same rrtype and rdlength as r1 +mDNSexport mDNSBool SameRDataBody(const ResourceRecord *const r1, const RDataBody *const r2) { - if (r1->rrtype != r2->rrtype) return(mDNSfalse); - if (r1->rdlength != r2->rdlength) return(mDNSfalse); - if (r1->rdatahash != r2->rdatahash) return(mDNSfalse); switch(r1->rrtype) { case kDNSType_CNAME:// Same as PTR - case kDNSType_PTR: return(SameDomainName(&r1->rdata->u.name, &r2->rdata->u.name)); + case kDNSType_PTR: return(SameDomainName(&r1->rdata->u.name, &r2->name)); - case kDNSType_SRV: return(mDNSBool)( r1->rdata->u.srv.priority == r2->rdata->u.srv.priority && - r1->rdata->u.srv.weight == r2->rdata->u.srv.weight && - r1->rdata->u.srv.port.NotAnInteger == r2->rdata->u.srv.port.NotAnInteger && - SameDomainName(&r1->rdata->u.srv.target, &r2->rdata->u.srv.target) ); + case kDNSType_SRV: return(mDNSBool)( r1->rdata->u.srv.priority == r2->srv.priority && + r1->rdata->u.srv.weight == r2->srv.weight && + r1->rdata->u.srv.port.NotAnInteger == r2->srv.port.NotAnInteger && + SameDomainName(&r1->rdata->u.srv.target, &r2->srv.target) ); - default: return(mDNSPlatformMemSame(r1->rdata->u.data, r2->rdata->u.data, r1->rdlength)); + default: return(mDNSPlatformMemSame(r1->rdata->u.data, r2->data, r1->rdlength)); } } +mDNSexport mDNSBool SameRData(const ResourceRecord *const r1, const ResourceRecord *const r2) + { + if (r1->rrtype != r2->rrtype) return(mDNSfalse); + if (r1->rdlength != r2->rdlength) return(mDNSfalse); + if (r1->rdatahash != r2->rdatahash) return(mDNSfalse); + return(SameRDataBody(r1, &r2->rdata->u)); + } + mDNSexport mDNSBool SameResourceRecord(ResourceRecord *r1, ResourceRecord *r2) { return (r1->namehash == r2->namehash && @@ -1797,11 +1851,10 @@ mDNSexport const mDNSu8 *GetLargeResourceRecord(mDNS *const m, const DNSMessage CacheRecord *rr = &largecr->r; mDNSu16 pktrdlength; - if (largecr == &m->rec && rr->resrec.RecordType) - LogMsg("GetLargeResourceRecord: m->rec appears to be already in use"); + if (largecr == &m->rec && largecr->r.resrec.RecordType) + LogMsg("GetLargeResourceRecord: m->rec appears to be already in use for %s", CRDisplayString(m, &largecr->r)); rr->next = mDNSNULL; - rr->resrec.RecordType = RecordType; rr->resrec.name = &largecr->namestorage; rr->NextInKAList = mDNSNULL; @@ -1833,7 +1886,7 @@ mDNSexport const mDNSu8 *GetLargeResourceRecord(mDNS *const m, const DNSMessage // us to look at. If we decide to copy it into the cache, then we'll update m->NextCacheCheck accordingly. pktrdlength = (mDNSu16)((mDNSu16)ptr[8] << 8 | ptr[9]); if (ptr[2] & (kDNSClass_UniqueRRSet >> 8)) - rr->resrec.RecordType |= kDNSRecordTypePacketUniqueMask; + RecordType |= kDNSRecordTypePacketUniqueMask; ptr += 10; if (ptr + pktrdlength > end) { debugf("GetResourceRecord: RDATA exceeds end of packet"); return(mDNSNULL); } end = ptr + pktrdlength; // Adjust end to indicate the end of the rdata for this resource record @@ -1917,6 +1970,8 @@ mDNSexport const mDNSu8 *GetLargeResourceRecord(mDNS *const m, const DNSMessage rr->resrec.namehash = DomainNameHashValue(rr->resrec.name); SetNewRData(&rr->resrec, mDNSNULL, 0); + // Success! Now fill in RecordType to show this record contains valid data + rr->resrec.RecordType = RecordType; return(ptr + pktrdlength); } diff --git a/mDNSCore/DNSCommon.h b/mDNSCore/DNSCommon.h index 13b7ca8..3ec6fc3 100644 --- a/mDNSCore/DNSCommon.h +++ b/mDNSCore/DNSCommon.h @@ -1,28 +1,32 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: DNSCommon.h,v $ +Revision 1.34.2.1 2006/08/29 06:24:22 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + +Revision 1.34 2006/03/18 21:47:56 cheshire + Improve logic for delaying packets after repeated interface transitions + +Revision 1.33 2006/03/10 21:51:41 cheshire + After record update, old record sometimes remains in cache +Split out SameRDataBody() into a separate routine so it can be called from other code + Revision 1.32 2005/03/21 00:33:51 shersche Fix build warnings on Win32 platform @@ -141,6 +145,7 @@ Revision 1.1 2003/12/13 03:05:27 ksekar extern "C" { #endif + // *************************************************************************** #if COMPILER_LIKES_PRAGMA_MARK #pragma mark - DNS Protocol Constants @@ -192,6 +197,7 @@ typedef enum TSIG_ErrBadTime = 18 } TSIG_ErrorCode; + // *************************************************************************** #if COMPILER_LIKES_PRAGMA_MARK #pragma mark - @@ -202,6 +208,7 @@ extern const NetworkInterfaceInfo *GetFirstActiveInterface(const NetworkInterfac extern mDNSInterfaceID GetNextActiveInterfaceID(const NetworkInterfaceInfo *intf); extern mDNSu32 mDNSRandom(mDNSu32 max); +extern mDNSu32 mDNSRandomFromFixedSeed(mDNSu32 seed, mDNSu32 max); // *************************************************************************** @@ -235,6 +242,7 @@ extern void mDNS_HostNameCallback(mDNS *const m, AuthRecord *const rr, mStatus r extern mDNSu32 RDataHashValue(mDNSu16 const rdlength, const RDataBody *const rdb); +extern mDNSBool SameRDataBody(const ResourceRecord *const r1, const RDataBody *const r2); extern mDNSBool SameRData(const ResourceRecord *const r1, const ResourceRecord *const r2); extern mDNSBool ResourceRecordAnswersQuestion(const ResourceRecord *const rr, const DNSQuestion *const q); @@ -330,6 +338,7 @@ extern const mDNSu8 *LocateAuthorities(const DNSMessage *const msg, const mDNSu8 extern const mDNSu8 *LocateAdditionals(const DNSMessage *const msg, const mDNSu8 *const end); + // *************************************************************************** #if COMPILER_LIKES_PRAGMA_MARK #pragma mark - @@ -340,6 +349,7 @@ extern const mDNSu8 *LocateAdditionals(const DNSMessage *const msg, const mDNSu8 extern mStatus mDNSSendDNSMessage(const mDNS *const m, DNSMessage *const msg, mDNSu8 *end, mDNSInterfaceID InterfaceID, const mDNSAddr *dst, mDNSIPPort dstport, int sd, uDNS_AuthInfo *authInfo); + // *************************************************************************** #if COMPILER_LIKES_PRAGMA_MARK #pragma mark - diff --git a/mDNSCore/DNSDigest.c b/mDNSCore/DNSDigest.c index 89d7b01..91b7078 100644 --- a/mDNSCore/DNSDigest.c +++ b/mDNSCore/DNSDigest.c @@ -1,28 +1,31 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: DNSDigest.c,v $ +Revision 1.15.2.1 2006/08/29 06:24:22 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + +Revision 1.15 2006/06/20 04:12:30 cheshire + DNS Update broken + +Revision 1.14 2006/02/25 23:12:07 cheshire + Fix to avoid code generation warning/error on FreeBSD 7 + Revision 1.13 2004/12/16 20:12:59 cheshire Cache memory management improvements @@ -1410,12 +1413,11 @@ mDNSexport mDNSu8 *DNSDigest_SignMessage(DNSMessage *msg, mDNSu8 **end, mDNSu16 rdata += 6; MD5_Update(&c, utc48, 6); - // fudge - buf = mDNSOpaque16fromIntVal(300); // 300 sec is fudge recommended in RFC 2485 - rdata[0] = buf.b[0]; - rdata[1] = buf.b[1]; + // 300 sec is fudge recommended in RFC 2485 + rdata[0] = (mDNSu8)((300 >> 8) & 0xff); + rdata[1] = (mDNSu8)( 300 & 0xff); + MD5_Update(&c, rdata, sizeof(mDNSOpaque16)); rdata += sizeof(mDNSOpaque16); - MD5_Update(&c, buf.b, sizeof(mDNSOpaque16)); // digest error and other data len (both zero) - we'll add them to the rdata later buf.NotAnInteger = 0; diff --git a/mDNSCore/mDNS.c b/mDNSCore/mDNS.c index 2098e1e..4eb8719 100755 --- a/mDNSCore/mDNS.c +++ b/mDNSCore/mDNS.c @@ -1,25 +1,18 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2002-2006 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ * * This code is completely 100% portable C. It does not depend on any external header files * from outside the mDNS project -- all the types it expects to find are defined right here. @@ -45,6 +38,26 @@ Change History (most recent first): $Log: mDNS.c,v $ +Revision 1.537.2.1 2006/08/29 06:24:22 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + +Revision 1.537 2006/03/19 02:00:07 cheshire + Improve logic for delaying packets after repeated interface transitions + +Revision 1.536 2006/03/08 23:29:53 cheshire + Improve "Service Renamed" log message + +Revision 1.535 2006/03/02 20:41:17 cheshire + After record update, old record sometimes remains in cache +Minor code tidying and comments to reduce the risk of similar programming errors in future + +Revision 1.534 2006/03/02 03:25:46 cheshire + After record update, old record sometimes remains in cache +Code to harmonize RRSet TTLs was inadvertently rescuing expiring records + +Revision 1.533 2006/02/26 00:54:41 cheshire +Fixes to avoid code generation warning/error on FreeBSD 7 + Revision 1.532 2005/12/02 20:24:36 cheshire Adjust cutoff time for KA list by one second @@ -1756,13 +1769,19 @@ mDNSexport const mDNSInterfaceID mDNSInterface_LocalOnly = (mDNSInterfaceID)1; mDNSlocal const mDNSInterfaceID mDNSInterfaceMark = (mDNSInterfaceID)~0; -#define UnicastDNSPortAsNumber 53 +#define UnicastDNSPortAsNumber 53 +#define NATPMPPortAsNumber 5351 +#define DNSEXTPortAsNumber 5352 // Port used for end-to-end DNS operations like LLQ, Updates with Leases, etc. #define MulticastDNSPortAsNumber 5353 +#define LoopbackIPCPortAsNumber 5354 + mDNSexport const mDNSIPPort UnicastDNSPort = { { UnicastDNSPortAsNumber >> 8, UnicastDNSPortAsNumber & 0xFF } }; +mDNSexport const mDNSIPPort NATPMPPort = { { NATPMPPortAsNumber >> 8, NATPMPPortAsNumber & 0xFF } }; +mDNSexport const mDNSIPPort DNSEXTPort = { { DNSEXTPortAsNumber >> 8, DNSEXTPortAsNumber & 0xFF } }; mDNSexport const mDNSIPPort MulticastDNSPort = { { MulticastDNSPortAsNumber >> 8, MulticastDNSPortAsNumber & 0xFF } }; +mDNSexport const mDNSIPPort LoopbackIPCPort = { { LoopbackIPCPortAsNumber >> 8, LoopbackIPCPortAsNumber & 0xFF } }; + mDNSexport const mDNSv4Addr AllDNSAdminGroup = { { 239, 255, 255, 251 } }; -mDNSexport const mDNSv4Addr AllDNSLinkGroupv4 = { { 224, 0, 0, 251 } }; -mDNSexport const mDNSv6Addr AllDNSLinkGroupv6 = { { 0xFF,0x02,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0xFB } }; mDNSexport const mDNSAddr AllDNSLinkGroup_v4 = { mDNSAddrType_IPv4, { { { 224, 0, 0, 251 } } } }; mDNSexport const mDNSAddr AllDNSLinkGroup_v6 = { mDNSAddrType_IPv6, { { { 0xFF,0x02,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0xFB } } } }; @@ -1951,8 +1970,8 @@ mDNSexport mDNSu32 mDNS_vsnprintf(char *sbuffer, mDNSu32 buflen, const char *fmt "%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X", a[0x0], a[0x1], a[0x2], a[0x3], a[0x4], a[0x5], a[0x6], a[0x7], a[0x8], a[0x9], a[0xA], a[0xB], a[0xC], a[0xD], a[0xE], a[0xF]); break; - default: i = mDNS_snprintf(mDNS_VACB, sizeof(mDNS_VACB), "%s", "<< ERROR: Must specify address size " - "(i.e. %.4a=IPv4, %.6a=Ethernet, %.16a=IPv6) >>"); break; + default: i = mDNS_snprintf(mDNS_VACB, sizeof(mDNS_VACB), "%s", "<< ERROR: Must specify" + " address size (i.e. %.4a=IPv4, %.6a=Ethernet, %.16a=IPv6) >>"); break; } } } @@ -2024,8 +2043,10 @@ mDNSexport mDNSu32 mDNS_vsnprintf(char *sbuffer, mDNSu32 buflen, const char *fmt if (*a == 0) *s++ = '.'; // Special case for root DNS name while (*a) { - if (*a > 63) { s += mDNS_snprintf(s, mDNS_VACB_Remain(s), "<>", *a); break; } - if (s + *a >= &mDNS_VACB[254]) { s += mDNS_snprintf(s, mDNS_VACB_Remain(s), "<>"); break; } + if (*a > 63) + { s += mDNS_snprintf(s, mDNS_VACB_Remain(s), "<>", *a); break; } + if (s + *a >= &mDNS_VACB[254]) + { s += mDNS_snprintf(s, mDNS_VACB_Remain(s), "<>"); break; } s += mDNS_snprintf(s, mDNS_VACB_Remain(s), "%#s.", a); a += 1 + *a; } @@ -2060,9 +2081,10 @@ mDNSexport mDNSu32 mDNS_vsnprintf(char *sbuffer, mDNSu32 buflen, const char *fmt } while (i < --F.fieldWidth); // Make sure we don't truncate in the middle of a UTF-8 character. - // Note: s[i] is the first eliminated character; i.e. the next character *after* the last character of the allowed output. If s[i] is a - // UTF-8 continuation character, then we've cut a unicode character in half, so back up 'i' until s[i] is no longer a UTF-8 continuation - // character. (if the input was proprly formed, s[i] will now be the UTF-8 start character of the multi-byte character we just eliminated). + // Note: s[i] is the first eliminated character; i.e. the next character *after* the last character of the + // allowed output. If s[i] is a UTF-8 continuation character, then we've cut a unicode character in half, + // so back up 'i' until s[i] is no longer a UTF-8 continuation character. (if the input was proprly + // formed, s[i] will now be the UTF-8 start character of the multi-byte character we just eliminated). if (i > buflen - nwritten) { i = buflen - nwritten; while (i>0 && (s[i] & 0xC0) == 0x80) i--; } for (j=0; jmDNS_reentrancy--; // Decrement to block mDNS API calls again } -// When a new local AuthRecord is created or deleted, AnswerLocalQuestions() runs though our LocalOnlyQuestions delivering answers to each, -// stopping if it reaches a NewLocalOnlyQuestion -- brand-new questions are handled by AnswerNewLocalOnlyQuestion(). +// When a new local AuthRecord is created or deleted, AnswerLocalQuestions() runs though our LocalOnlyQuestions delivering answers +// to each, stopping if it reaches a NewLocalOnlyQuestion -- brand-new questions are handled by AnswerNewLocalOnlyQuestion(). // If the AuthRecord is marked mDNSInterface_LocalOnly, then we also deliver it to any other questions we have using mDNSInterface_Any. // Used by AnswerForNewLocalRecords() and mDNS_Deregister_internal() mDNSlocal void AnswerLocalQuestions(mDNS *const m, AuthRecord *rr, mDNSBool AddRecord) @@ -2299,7 +2321,11 @@ mDNSlocal mDNSBool SameResourceRecordSignature(const ResourceRecord *const r1, c if (r1->InterfaceID && r2->InterfaceID && r1->InterfaceID != r2->InterfaceID) return(mDNSfalse); - return(mDNSBool)(r1->rrtype == r2->rrtype && r1->rrclass == r2->rrclass && r1->namehash == r2->namehash && SameDomainName(r1->name, r2->name)); + return(mDNSBool)( + r1->rrtype == r2->rrtype && + r1->rrclass == r2->rrclass && + r1->namehash == r2->namehash && + SameDomainName(r1->name, r2->name)); } // PacketRRMatchesSignature behaves as SameResourceRecordSignature, except that types may differ if our @@ -2315,7 +2341,10 @@ mDNSlocal mDNSBool PacketRRMatchesSignature(const CacheRecord *const pktrr, cons authrr->resrec.InterfaceID && pktrr->resrec.InterfaceID != authrr->resrec.InterfaceID) return(mDNSfalse); if (!(authrr->resrec.RecordType & kDNSRecordTypeUniqueMask) && pktrr->resrec.rrtype != authrr->resrec.rrtype) return(mDNSfalse); - return(mDNSBool)(pktrr->resrec.rrclass == authrr->resrec.rrclass && pktrr->resrec.namehash == authrr->resrec.namehash && SameDomainName(pktrr->resrec.name, authrr->resrec.name)); + return(mDNSBool)( + pktrr->resrec.rrclass == authrr->resrec.rrclass && + pktrr->resrec.namehash == authrr->resrec.namehash && + SameDomainName(pktrr->resrec.name, authrr->resrec.name)); } // IdenticalResourceRecord returns true if two resources records have @@ -2324,7 +2353,8 @@ mDNSlocal mDNSBool IdenticalResourceRecord(const ResourceRecord *const r1, const { if (!r1) { LogMsg("IdenticalResourceRecord ERROR: r1 is NULL"); return(mDNSfalse); } if (!r2) { LogMsg("IdenticalResourceRecord ERROR: r2 is NULL"); return(mDNSfalse); } - if (r1->rrtype != r2->rrtype || r1->rrclass != r2->rrclass || r1->namehash != r2->namehash || !SameDomainName(r1->name, r2->name)) return(mDNSfalse); + if (r1->rrtype != r2->rrtype || r1->rrclass != r2->rrclass || r1->namehash != r2->namehash || !SameDomainName(r1->name, r2->name)) + return(mDNSfalse); return(SameRData(r1, r2)); } @@ -2356,7 +2386,8 @@ mDNSlocal void SetNextAnnounceProbeTime(mDNS *const m, const AuthRecord *const r { if (rr->resrec.RecordType == kDNSRecordTypeUnique) { - //LogMsg("ProbeCount %d Next %ld %s", rr->ProbeCount, (rr->LastAPTime + rr->ThisAPInterval) - m->timenow, ARDisplayString(m, rr)); + //LogMsg("ProbeCount %d Next %ld %s", + // rr->ProbeCount, (rr->LastAPTime + rr->ThisAPInterval) - m->timenow, ARDisplayString(m, rr)); if (m->NextScheduledProbe - (rr->LastAPTime + rr->ThisAPInterval) >= 0) m->NextScheduledProbe = (rr->LastAPTime + rr->ThisAPInterval); } @@ -2436,7 +2467,8 @@ mDNSlocal void SetTargetToHostName(mDNS *const m, AuthRecord *const rr) // changing to the new rdata. However, in practice, we only do SetTargetToHostName for unique records, // so when we announce them we'll set the kDNSClass_UniqueRRSet and clear any stale data that way. if (rr->RequireGoodbye && rr->resrec.RecordType == kDNSRecordTypeShared) - debugf("Have announced shared record %##s (%s) at least once: should have sent a goodbye packet before updating", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); + debugf("Have announced shared record %##s (%s) at least once: should have sent a goodbye packet before updating", + rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); rr->AnnounceCount = InitialAnnounceCount; rr->RequireGoodbye = mDNSfalse; @@ -2459,8 +2491,10 @@ mDNSlocal void AcknowledgeRecord(mDNS *const m, AuthRecord *const rr) } // Two records qualify to be local duplicates if the RecordTypes are the same, or if one is Unique and the other Verified -#define RecordLDT(A,B) ((A)->resrec.RecordType == (B)->resrec.RecordType || ((A)->resrec.RecordType | (B)->resrec.RecordType) == (kDNSRecordTypeUnique | kDNSRecordTypeVerified)) -#define RecordIsLocalDuplicate(A,B) ((A)->resrec.InterfaceID == (B)->resrec.InterfaceID && RecordLDT((A),(B)) && IdenticalResourceRecord(&(A)->resrec, &(B)->resrec)) +#define RecordLDT(A,B) ((A)->resrec.RecordType == (B)->resrec.RecordType || \ + ((A)->resrec.RecordType | (B)->resrec.RecordType) == (kDNSRecordTypeUnique | kDNSRecordTypeVerified)) +#define RecordIsLocalDuplicate(A,B) \ + ((A)->resrec.InterfaceID == (B)->resrec.InterfaceID && RecordLDT((A),(B)) && IdenticalResourceRecord(&(A)->resrec, &(B)->resrec)) mDNSlocal mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr) { @@ -2484,7 +2518,8 @@ mDNSlocal mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr) while (*d && *d != rr) d=&(*d)->next; if (*d || *p) { - LogMsg("Error! Tried to register a AuthRecord %p %##s (%s) that's already in the list", rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); + LogMsg("Error! Tried to register a AuthRecord %p %##s (%s) that's already in the list", + rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); return(mStatus_AlreadyRegistered); } @@ -2710,7 +2745,8 @@ mDNSlocal mStatus mDNS_Deregister_internal(mDNS *const m, AuthRecord *const rr, if (*d) { AuthRecord *dup = *d; - debugf("Duplicate record %p taking over from %p %##s (%s)", dup, rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); + debugf("Duplicate record %p taking over from %p %##s (%s)", + dup, rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); *d = dup->next; // Cut replacement record from DuplicateRecords list dup->next = rr->next; // And then... rr->next = dup; // ... splice it in right after the record we're about to delete @@ -2739,14 +2775,16 @@ mDNSlocal mStatus mDNS_Deregister_internal(mDNS *const m, AuthRecord *const rr, while (*p && *p != rr) p=&(*p)->next; // If we found our record on the duplicate list, then make sure we don't send a goodbye for it if (*p) rr->RequireGoodbye = mDNSfalse; - if (*p) debugf("DNS_Deregister_internal: Deleting DuplicateRecord %p %##s (%s)", rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); + if (*p) debugf("DNS_Deregister_internal: Deleting DuplicateRecord %p %##s (%s)", + rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); } if (!*p) { // No need to log an error message if we already know this is a potentially repeated deregistration if (drt != mDNS_Dereg_repeat) - LogMsg("mDNS_Deregister_internal: Record %p %##s (%s) not found in list", rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); + LogMsg("mDNS_Deregister_internal: Record %p %##s (%s) not found in list", + rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); return(mStatus_BadReferenceErr); } @@ -2754,7 +2792,8 @@ mDNSlocal mStatus mDNS_Deregister_internal(mDNS *const m, AuthRecord *const rr, // we need to retract that announcement before we delete the record if (RecordType == kDNSRecordTypeShared && rr->RequireGoodbye) { - verbosedebugf("mDNS_Deregister_internal: Sending deregister for %##s (%s)", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); + verbosedebugf("mDNS_Deregister_internal: Sending deregister for %##s (%s)", + rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); rr->resrec.RecordType = kDNSRecordTypeDeregistering; rr->resrec.rroriginalttl = 0; rr->ImmedAnswer = mDNSInterfaceMark; @@ -2777,7 +2816,8 @@ mDNSlocal mStatus mDNS_Deregister_internal(mDNS *const m, AuthRecord *const rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); else { - verbosedebugf("mDNS_Deregister_internal: Deleting record for %##s (%s)", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); + verbosedebugf("mDNS_Deregister_internal: Deleting record for %##s (%s)", + rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); rr->resrec.RecordType = kDNSRecordTypeUnregistered; } @@ -3067,7 +3107,8 @@ mDNSlocal void SendResponses(mDNS *const m) { for (r2 = m->ResourceRecords; r2; r2=r2->next) if (ResourceRecordIsValidAnswer(r2)) - if (r2->ImmedAnswer != mDNSInterfaceMark && r2->ImmedAnswer != rr->ImmedAnswer && SameResourceRecordSignature(&r2->resrec, &rr->resrec)) + if (r2->ImmedAnswer != mDNSInterfaceMark && + r2->ImmedAnswer != rr->ImmedAnswer && SameResourceRecordSignature(&r2->resrec, &rr->resrec)) r2->ImmedAnswer = rr->ImmedAnswer; } else if (rr->ImmedAdditional) // If we're sending this as additional, see that its whole RRSet is similarly marked @@ -3301,10 +3342,11 @@ mDNSlocal void SendResponses(mDNS *const m) // Note: MUST call SetNextCacheCheckTime any time we change: // rr->TimeRcvd -// rr->DelayDelivery // rr->resrec.rroriginalttl // rr->UnansweredQueries // rr->CRActiveQuestion +// Also, any time we set rr->DelayDelivery we should call SetNextCacheCheckTime to ensure m->NextCacheCheck is set if necessary +// Clearing rr->DelayDelivery does not require a call to SetNextCacheCheckTime mDNSlocal void SetNextCacheCheckTime(mDNS *const m, CacheRecord *const rr) { rr->NextRequiredQuery = RRExpireTime(rr); @@ -3315,8 +3357,9 @@ mDNSlocal void SetNextCacheCheckTime(mDNS *const m, CacheRecord *const rr) { rr->NextRequiredQuery -= TicksTTL(rr)/20 * (MaxUnansweredQueries - rr->UnansweredQueries); rr->NextRequiredQuery += mDNSRandom((mDNSu32)TicksTTL(rr)/50); - verbosedebugf("SetNextCacheCheckTime: %##s (%s) NextRequiredQuery in %ld sec", - rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), (rr->NextRequiredQuery - m->timenow) / mDNSPlatformOneSecond); + verbosedebugf("SetNextCacheCheckTime: %##s (%s) NextRequiredQuery in %ld sec CacheCheckGracePeriod %d ticks", + rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), + (rr->NextRequiredQuery - m->timenow) / mDNSPlatformOneSecond, CacheCheckGracePeriod(rr)); } if (m->NextCacheCheck - (rr->NextRequiredQuery + CacheCheckGracePeriod(rr)) > 0) @@ -3327,9 +3370,10 @@ mDNSlocal void SetNextCacheCheckTime(mDNS *const m, CacheRecord *const rr) m->NextCacheCheck = rr->DelayDelivery; } -#define kDefaultReconfirmTimeForNoAnswer ((mDNSu32)mDNSPlatformOneSecond * 15) -#define kDefaultReconfirmTimeForCableDisconnect ((mDNSu32)mDNSPlatformOneSecond * 5) -#define kMinimumReconfirmTime ((mDNSu32)mDNSPlatformOneSecond * 5) +#define kMinimumReconfirmTime ((mDNSu32)mDNSPlatformOneSecond * 5) +#define kDefaultReconfirmTimeForWake ((mDNSu32)mDNSPlatformOneSecond * 5) +#define kDefaultReconfirmTimeForNoAnswer ((mDNSu32)mDNSPlatformOneSecond * 15) +#define kDefaultReconfirmTimeForFlappingInterface ((mDNSu32)mDNSPlatformOneSecond * 30) mDNSlocal mStatus mDNS_Reconfirm_internal(mDNS *const m, CacheRecord *const rr, mDNSu32 interval) { @@ -3342,12 +3386,15 @@ mDNSlocal mStatus mDNS_Reconfirm_internal(mDNS *const m, CacheRecord *const rr, if (RRExpireTime(rr) - m->timenow > (mDNSs32)((interval * 4) / 3)) { // Add a 33% random amount to the interval, to avoid synchronization between multiple hosts - interval += mDNSRandom(interval/3); + // For all the reconfirmations in a given batch, we want to use the same random value + // so that the reconfirmation questions can be grouped into a single query packet + if (!m->RandomReconfirmDelay) m->RandomReconfirmDelay = 1 + mDNSRandom(0x3FFFFFFF); + interval += mDNSRandomFromFixedSeed(m->RandomReconfirmDelay, interval/3); rr->TimeRcvd = m->timenow - (mDNSs32)interval * 3; - rr->resrec.rroriginalttl = interval * 4 / mDNSPlatformOneSecond; + rr->resrec.rroriginalttl = (interval * 4 + mDNSPlatformOneSecond - 1) / mDNSPlatformOneSecond; SetNextCacheCheckTime(m, rr); } - debugf("mDNS_Reconfirm_internal:%5ld ticks to go for %s", RRExpireTime(rr) - m->timenow, CRDisplayString(m, rr)); + debugf("mDNS_Reconfirm_internal:%6ld ticks to go for %s", RRExpireTime(rr) - m->timenow, CRDisplayString(m, rr)); return(mStatus_NoError); } @@ -3370,7 +3417,8 @@ mDNSlocal mDNSBool BuildQuestion(mDNS *const m, DNSMessage *query, mDNSu8 **quer } else if (newptr + *answerforecast >= limit) { - verbosedebugf("BuildQuestion: Retracting question %##s new forecast total %d", q->qname.c, newptr + *answerforecast - query->data); + verbosedebugf("BuildQuestion: Retracting question %##s new forecast total %d", + q->qname.c, newptr + *answerforecast - query->data); query->h.numQuestions--; return(mDNSfalse); } @@ -3553,6 +3601,10 @@ mDNSlocal mDNSBool AccelerateThisQuery(mDNS *const m, DNSQuestion *q) mDNSlocal void SendQueries(mDNS *const m) { + mDNSu32 slot; + CacheGroup *cg; + CacheRecord *cr; + AuthRecord *ar; int pktcount = 0; DNSQuestion *q; // For explanation of maxExistingQuestionInterval logic, see comments for maxExistingAnnounceInterval @@ -3563,8 +3615,6 @@ mDNSlocal void SendQueries(mDNS *const m) // 1. If time for a query, work out what we need to do if (m->timenow - m->NextScheduledQuery >= 0) { - mDNSu32 slot; - CacheGroup *cg; CacheRecord *rr; m->NextScheduledQuery = m->timenow + 0x78000000; @@ -3618,7 +3668,8 @@ mDNSlocal void SendQueries(mDNS *const m) (!q->Target.type && ActiveQuestion(q) && q->ThisQInterval <= maxExistingQuestionInterval && AccelerateThisQuery(m,q))) { // If at least halfway to next query time, advance to next interval - // If less than halfway to next query time, treat this as logically a repeat of the last transmission, without advancing the interval + // If less than halfway to next query time, then + // treat this as logically a repeat of the last transmission, without advancing the interval if (m->timenow - (q->LastQTime + q->ThisQInterval/2) >= 0) { q->SendQNow = mDNSInterfaceMark; // Mark this question for sending on all interfaces @@ -3627,8 +3678,9 @@ mDNSlocal void SendQueries(mDNS *const m) q->ThisQInterval = MaxQuestionInterval; else if (q->CurrentAnswers == 0 && q->ThisQInterval == InitialQuestionInterval * 8) { - debugf("SendQueries: Zero current answers for %##s (%s); will reconfirm antecedents", q->qname.c, DNSTypeName(q->qtype)); - ReconfirmAntecedents(m, q); // If sending third query, and no answers yet, time to begin doubting the source + debugf("SendQueries: Zero current answers for %##s (%s); will reconfirm antecedents", + q->qname.c, DNSTypeName(q->qtype)); + ReconfirmAntecedents(m, q); // Sending third query, and no answers yet; time to begin doubting the source } } @@ -3680,7 +3732,8 @@ mDNSlocal void SendQueries(mDNS *const m) rr->ProbeCount--; SetNextAnnounceProbeTime(m, rr); } - // else, if it has now finished probing, move it to state Verified, and update m->NextScheduledResponse so it will be announced + // else, if it has now finished probing, move it to state Verified, + // and update m->NextScheduledResponse so it will be announced else { AuthRecord *r2; @@ -3706,7 +3759,8 @@ mDNSlocal void SendQueries(mDNS *const m) } } - // 3. Now we know which queries and probes we're sending, go through our interface list sending the appropriate queries on each interface + // 3. Now we know which queries and probes we're sending, + // go through our interface list sending the appropriate queries on each interface while (intf) { AuthRecord *rr; @@ -3748,11 +3802,13 @@ mDNSlocal void SendQueries(mDNS *const m) answerforecast = forecast; rr->SendRNow = (rr->resrec.InterfaceID) ? mDNSNULL : GetNextActiveInterfaceID(intf); rr->IncludeInProbe = mDNStrue; - verbosedebugf("SendQueries: Put Question %##s (%s) probecount %d", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), rr->ProbeCount); + verbosedebugf("SendQueries: Put Question %##s (%s) probecount %d", + rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), rr->ProbeCount); } else { - verbosedebugf("SendQueries: Retracting Question %##s (%s)", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); + verbosedebugf("SendQueries: Retracting Question %##s (%s)", + rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); m->omsg.h.numQuestions--; } } @@ -3766,7 +3822,8 @@ mDNSlocal void SendQueries(mDNS *const m) mDNSu8 *newptr = PutResourceRecordTTL(&m->omsg, queryptr, &m->omsg.h.numAnswers, &rr->resrec, rr->resrec.rroriginalttl - SecsSinceRcvd); if (newptr) { - verbosedebugf("SendQueries: Put %##s (%s) at %d - %d", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), queryptr - m->omsg.data, newptr - m->omsg.data); + verbosedebugf("SendQueries: Put %##s (%s) at %d - %d", + rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), queryptr - m->omsg.data, newptr - m->omsg.data); queryptr = newptr; KnownAnswerList = rr->NextInKAList; rr->NextInKAList = mDNSNULL; @@ -3819,17 +3876,39 @@ mDNSlocal void SendQueries(mDNS *const m) } } - // Final sanity check for debugging purposes - { - AuthRecord *rr; - for (rr = m->ResourceRecords; rr; rr=rr->next) - if (rr->SendRNow) - { - if (rr->resrec.InterfaceID != mDNSInterface_LocalOnly) - LogMsg("SendQueries: No active interface to send: %s", ARDisplayString(m, rr)); - rr->SendRNow = mDNSNULL; - } - } + // 4. Final housekeeping + + // 4a. Debugging check: Make sure we announced all our records + for (ar = m->ResourceRecords; ar; ar=ar->next) + if (ar->SendRNow) + { + if (ar->resrec.InterfaceID != mDNSInterface_LocalOnly) + LogMsg("SendQueries: No active interface to send: %s", ARDisplayString(m, ar)); + ar->SendRNow = mDNSNULL; + } + + // 4b. When we have lingering cache records that we're keeping around for a few seconds in the hope + // that their interface which went away might come back again, the logic will want to send queries + // for those records, but we can't because their interface isn't here any more, so to keep the + // state machine ticking over we just pretend we did so. + // If the interface does not come back in time, the cache record will expire naturally + FORALL_CACHERECORDS(slot, cg, cr) + if (cr->CRActiveQuestion && cr->UnansweredQueries < MaxUnansweredQueries && m->timenow - cr->NextRequiredQuery >= 0) + { + cr->UnansweredQueries++; + cr->CRActiveQuestion->SendQNow = mDNSNULL; + SetNextCacheCheckTime(m, cr); + } + + // 4c. Debugging check: Make sure we sent all our planned questions + // Do this AFTER the lingering cache records check above, because that will prevent spurious warnings for questions + // we legitimately couldn't send because the interface is no longer available + for (q = m->Questions; q; q=q->next) + if (q->SendQNow) + { + LogMsg("SendQueries: No active interface to send: %##s %s", q->qname.c, DNSTypeName(q->qtype)); + q->SendQNow = mDNSNULL; + } } // *************************************************************************** @@ -3888,7 +3967,7 @@ mDNSlocal void AnswerQuestionWithResourceRecord(mDNS *const m, DNSQuestion *q, C mDNSlocal void CacheRecordDeferredAdd(mDNS *const m, CacheRecord *rr) { - rr->DelayDelivery = 0; + rr->DelayDelivery = 0; // Note, only need to call SetNextCacheCheckTime() when DelayDelivery is set, not when it's cleared if (m->CurrentQuestion) LogMsg("CacheRecordDeferredAdd ERROR m->CurrentQuestion already set"); m->CurrentQuestion = m->Questions; while (m->CurrentQuestion && m->CurrentQuestion != m->NewQuestions) @@ -3935,11 +4014,12 @@ mDNSlocal void CacheRecordAdd(mDNS *const m, CacheRecord *rr) m->CurrentQuestion = q->next; if (ResourceRecordAnswersQuestion(&rr->resrec, q)) { - // If this question is one that's actively sending queries, and it's received ten answers within one second of sending the last - // query packet, then that indicates some radical network topology change, so reset its exponential backoff back to the start. - // We must be at least at the eight-second interval to do this. If we're at the four-second interval, or less, - // there's not much benefit accelerating because we will anyway send another query within a few seconds. - // The first reset query is sent out randomized over the next four seconds to reduce possible synchronization between machines. + // If this question is one that's actively sending queries, and it's received ten answers within one + // second of sending the last query packet, then that indicates some radical network topology change, + // so reset its exponential backoff back to the start. We must be at least at the eight-second interval + // to do this. If we're at the four-second interval, or less, there's not much benefit accelerating + // because we will anyway send another query within a few seconds. The first reset query is sent out + // randomized over the next four seconds to reduce possible synchronization between machines. if (q->LastAnswerPktNum != m->PktNum) { q->LastAnswerPktNum = m->PktNum; @@ -3953,7 +4033,8 @@ mDNSlocal void CacheRecordAdd(mDNS *const m, CacheRecord *rr) SetNextQueryTime(m,q); } } - verbosedebugf("CacheRecordAdd %p %##s (%s) %lu", rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), rr->resrec.rroriginalttl); + verbosedebugf("CacheRecordAdd %p %##s (%s) %lu", + rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), rr->resrec.rroriginalttl); q->CurrentAnswers++; if (rr->resrec.rdlength > SmallRecordLimit) q->LargeAnswers++; if (rr->resrec.RecordType & kDNSRecordTypePacketUniqueMask) q->UniqueAnswers++; @@ -3971,6 +4052,7 @@ mDNSlocal void CacheRecordAdd(mDNS *const m, CacheRecord *rr) } } m->CurrentQuestion = mDNSNULL; + SetNextCacheCheckTime(m, rr); } // NoCacheAnswer is only called from mDNSCoreReceiveResponse, *never* directly as a result of a client API call. @@ -3986,7 +4068,7 @@ mDNSlocal void CacheRecordAdd(mDNS *const m, CacheRecord *rr) mDNSlocal void NoCacheAnswer(mDNS *const m, CacheRecord *rr) { LogMsg("No cache space: Delivering non-cached result for %##s", m->rec.r.resrec.name->c); - if (m->CurrentQuestion) LogMsg("CacheRecordAdd ERROR m->CurrentQuestion already set"); + if (m->CurrentQuestion) LogMsg("NoCacheAnswer ERROR m->CurrentQuestion already set"); m->CurrentQuestion = m->Questions; while (m->CurrentQuestion) { @@ -4017,9 +4099,10 @@ mDNSlocal void CacheRecordRmv(mDNS *const m, CacheRecord *rr) m->CurrentQuestion = q->next; if (ResourceRecordAnswersQuestion(&rr->resrec, q)) { - verbosedebugf("CacheRecordRmv %p %##s (%s)", rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); + verbosedebugf("CacheRecordRmv %p %s", rr, CRDisplayString(m, rr)); if (q->CurrentAnswers == 0) - LogMsg("CacheRecordRmv ERROR: How can CurrentAnswers already be zero for %p %##s (%s)?", q, q->qname.c, DNSTypeName(q->qtype)); + LogMsg("CacheRecordRmv ERROR: How can CurrentAnswers already be zero for %p %##s (%s)?", + q, q->qname.c, DNSTypeName(q->qtype)); else { q->CurrentAnswers--; @@ -4028,9 +4111,11 @@ mDNSlocal void CacheRecordRmv(mDNS *const m, CacheRecord *rr) } if (q->CurrentAnswers == 0) { - debugf("CacheRecordRmv: Zero current answers for %##s (%s); will reconfirm antecedents", q->qname.c, DNSTypeName(q->qtype)); + debugf("CacheRecordRmv: Zero current answers for %##s (%s); will reconfirm antecedents", + q->qname.c, DNSTypeName(q->qtype)); ReconfirmAntecedents(m, q); } + q->FlappingInterface = mDNSNULL; AnswerQuestionWithResourceRecord(m, q, rr, mDNSfalse); // MUST NOT dereference q again after calling AnswerQuestionWithResourceRecord() } @@ -4053,8 +4138,10 @@ mDNSlocal void ReleaseCacheGroup(mDNS *const m, CacheGroup **cp) { CacheEntity *e = (CacheEntity *)(*cp); //LogMsg("ReleaseCacheGroup: Releasing CacheGroup for %p, %##s", (*cp)->name->c, (*cp)->name->c); - if ((*cp)->rrcache_tail != &(*cp)->members) LogMsg("ERROR: (*cp)->members == mDNSNULL but (*cp)->rrcache_tail != &(*cp)->members)"); - //if ((*cp)->name != (domainname*)((*cp)->namestorage)) LogMsg("ReleaseCacheGroup: %##s, %p %p", (*cp)->name->c, (*cp)->name, (domainname*)((*cp)->namestorage)); + if ((*cp)->rrcache_tail != &(*cp)->members) + LogMsg("ERROR: (*cp)->members == mDNSNULL but (*cp)->rrcache_tail != &(*cp)->members)"); + //if ((*cp)->name != (domainname*)((*cp)->namestorage)) + // LogMsg("ReleaseCacheGroup: %##s, %p %p", (*cp)->name->c, (*cp)->name, (domainname*)((*cp)->namestorage)); if ((*cp)->name != (domainname*)((*cp)->namestorage)) mDNSPlatformMemFree((*cp)->name); (*cp)->name = mDNSNULL; *cp = (*cp)->next; // Cut record from list @@ -4068,8 +4155,9 @@ mDNSlocal void ReleaseCacheRecord(mDNS *const m, CacheRecord *r) ReleaseCacheEntity(m, (CacheEntity *)r); } -// Note: We want to be careful that we deliver all the CacheRecordRmv calls before delivering CacheRecordDeferredAdd calls -// The in-order nature of the cache lists ensures that all callbacks for old records are delivered before callbacks for newer records +// Note: We want to be careful that we deliver all the CacheRecordRmv calls before delivering +// CacheRecordDeferredAdd calls. The in-order nature of the cache lists ensures that all +// callbacks for old records are delivered before callbacks for newer records. mDNSlocal void CheckCacheExpiration(mDNS *const m, CacheGroup *cg) { CacheRecord **rp = &cg->members; @@ -4109,11 +4197,13 @@ mDNSlocal void CheckCacheExpiration(mDNS *const m, CacheGroup *cg) // SendQueries() will see that we have records close to expiration, and send FEQs for them. m->NextScheduledQuery = m->timenow; // After sending the query we'll increment UnansweredQueries and call SetNextCacheCheckTime(), - // which will correctly update m->NextCacheCheck for us + // which will correctly update m->NextCacheCheck for us. event = m->timenow + 0x3FFFFFFF; } } } + verbosedebugf("CheckCacheExpiration:%6d %5d %s", + (event-m->timenow) / mDNSPlatformOneSecond, CacheCheckGracePeriod(rr), CRDisplayString(m, rr)); if (m->NextCacheCheck - (event + CacheCheckGracePeriod(rr)) > 0) m->NextCacheCheck = (event + CacheCheckGracePeriod(rr)); rp = &rr->next; @@ -4202,8 +4292,8 @@ mDNSlocal void AnswerNewQuestion(mDNS *const m) m->lock_rrcache = 0; } -// When a NewLocalOnlyQuestion is created, AnswerNewLocalOnlyQuestion runs though our ResourceRecords delivering any appropriate answers, -// stopping if it reaches a NewLocalRecord -- these will be handled by AnswerLocalQuestions +// When a NewLocalOnlyQuestion is created, AnswerNewLocalOnlyQuestion runs though our ResourceRecords delivering any +// appropriate answers, stopping if it reaches a NewLocalRecord -- these will be handled by AnswerLocalQuestions mDNSlocal void AnswerNewLocalOnlyQuestion(mDNS *const m) { DNSQuestion *q = m->NewLocalOnlyQuestions; // Grab the question we're going to answer @@ -4288,7 +4378,8 @@ mDNSlocal CacheEntity *GetCacheEntity(mDNS *const m, const CacheGroup *const Pre ReleaseCacheRecord(m, rr); } } - if ((*cp)->rrcache_tail != rp) verbosedebugf("GetFreeCacheRR: Updating rrcache_tail[%lu] from %p to %p", slot, (*cp)->rrcache_tail, rp); + if ((*cp)->rrcache_tail != rp) + verbosedebugf("GetFreeCacheRR: Updating rrcache_tail[%lu] from %p to %p", slot, (*cp)->rrcache_tail, rp); (*cp)->rrcache_tail = rp; if ((*cp)->members || (*cp)==PreserveCG) cp=&(*cp)->next; else ReleaseCacheGroup(m, cp); @@ -4343,7 +4434,8 @@ mDNSlocal CacheGroup *GetCacheGroup(mDNS *const m, const mDNSu32 slot, const Res cg->members = mDNSNULL; cg->rrcache_tail = &cg->members; cg->name = (domainname*)cg->namestorage; - //LogMsg("GetCacheGroup: %-10s %d-byte cache name %##s", (namelen > InlineCacheGroupNameSize) ? "Allocating" : "Inline", namelen, rr->name->c); + //LogMsg("GetCacheGroup: %-10s %d-byte cache name %##s", + // (namelen > InlineCacheGroupNameSize) ? "Allocating" : "Inline", namelen, rr->name->c); if (namelen > InlineCacheGroupNameSize) cg->name = mDNSPlatformMemAllocate(namelen); if (!cg->name) { @@ -4421,6 +4513,7 @@ mDNSexport mDNSs32 mDNS_Execute(mDNS *const m) else ReleaseCacheGroup(m, cp); } } + LogOperation("Cache checked. Next in %ld ticks", m->NextCacheCheck - m->timenow); } // 4. See if we can answer any of our new local questions from the cache @@ -4448,10 +4541,10 @@ mDNSexport mDNSs32 mDNS_Execute(mDNS *const m) { // If the platform code is ready, and we're not suppressing packet generation right now // then send our responses, probes, and questions. - // We check the cache first, because there might be records close to expiring that trigger questions to refresh them + // We check the cache first, because there might be records close to expiring that trigger questions to refresh them. // We send queries next, because there might be final-stage probes that complete their probing here, causing // them to advance to announcing state, and we want those to be included in any announcements we send out. - // Finally, we send responses, including the previously mentioned records that just completed probing + // Finally, we send responses, including the previously mentioned records that just completed probing. m->SuppressSending = 0; // 6. Send Query packets. This may cause some probing records to advance to announcing state @@ -4476,7 +4569,9 @@ mDNSexport mDNSs32 mDNS_Execute(mDNS *const m) } } - m->RandomQueryDelay = 0; // Clear m->RandomQueryDelay, ready to pick a new different value, when necessary + // Clear RandomDelay values, ready to pick a new different value next time + m->RandomQueryDelay = 0; + m->RandomReconfirmDelay = 0; } // Note about multi-threaded systems: @@ -4562,7 +4657,7 @@ mDNSexport void mDNSCoreMachineSleep(mDNS *const m, mDNSBool sleepstate) // 2. Re-validate our cache records m->NextCacheCheck = m->timenow; FORALL_CACHERECORDS(slot, cg, cr) - mDNS_Reconfirm_internal(m, cr, kDefaultReconfirmTimeForCableDisconnect); + mDNS_Reconfirm_internal(m, cr, kDefaultReconfirmTimeForWake); // 3. Retrigger probing and announcing for all our authoritative records for (rr = m->ResourceRecords; rr; rr=rr->next) @@ -4805,8 +4900,8 @@ mDNSlocal CacheRecord *FindIdenticalRecordInCache(const mDNS *const m, ResourceR // ProcessQuery examines a received query to see if we have any answers to give mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, const mDNSu8 *const end, - const mDNSAddr *srcaddr, const mDNSInterfaceID InterfaceID, mDNSBool LegacyQuery, mDNSBool QueryWasMulticast, mDNSBool QueryWasLocalUnicast, - DNSMessage *const response) + const mDNSAddr *srcaddr, const mDNSInterfaceID InterfaceID, mDNSBool LegacyQuery, mDNSBool QueryWasMulticast, + mDNSBool QueryWasLocalUnicast, DNSMessage *const response) { mDNSBool FromLocalSubnet = AddressIsLocalSubnet(m, InterfaceID, srcaddr); AuthRecord *ResponseRecords = mDNSNULL; @@ -4926,7 +5021,9 @@ mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, con if (!q->Target.type && ActiveQuestion(q) && m->timenow - q->LastQTxTime > mDNSPlatformOneSecond / 4) if (!q->InterfaceID || q->InterfaceID == InterfaceID) if (q->NextInDQList == mDNSNULL && dqp != &q->NextInDQList) - if (q->qtype == pktq.qtype && q->qclass == pktq.qclass && q->qnamehash == pktq.qnamehash && SameDomainName(&q->qname, &pktq.qname)) + if (q->qtype == pktq.qtype && + q->qclass == pktq.qclass && + q->qnamehash == pktq.qnamehash && SameDomainName(&q->qname, &pktq.qname)) { *dqp = q; dqp = &q->NextInDQList; } } } @@ -5232,7 +5329,8 @@ mDNSlocal void mDNSCoreReceiveQuery(mDNS *const m, const DNSMessage *const msg, if (!InterfaceID && mDNSAddrIsDNSMulticast(dstaddr)) { - LogMsg("Ignoring Query from %#-15a:%-5d to %#-15a:%-5d on 0x%p with %2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s (Multicast, but no InterfaceID)", + LogMsg("Ignoring Query from %#-15a:%-5d to %#-15a:%-5d on 0x%p with " + "%2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s (Multicast, but no InterfaceID)", srcaddr, mDNSVal16(srcport), dstaddr, mDNSVal16(dstport), InterfaceID, msg->h.numQuestions, msg->h.numQuestions == 1 ? ", " : "s,", msg->h.numAnswers, msg->h.numAnswers == 1 ? ", " : "s,", @@ -5241,7 +5339,8 @@ mDNSlocal void mDNSCoreReceiveQuery(mDNS *const m, const DNSMessage *const msg, return; } - verbosedebugf("Received Query from %#-15a:%-5d to %#-15a:%-5d on 0x%p with %2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s", + verbosedebugf("Received Query from %#-15a:%-5d to %#-15a:%-5d on 0x%p with " + "%2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s", srcaddr, mDNSVal16(srcport), dstaddr, mDNSVal16(dstport), InterfaceID, msg->h.numQuestions, msg->h.numQuestions == 1 ? ", " : "s,", msg->h.numAnswers, msg->h.numAnswers == 1 ? ", " : "s,", @@ -5290,7 +5389,8 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m, (void)srcport; (void)dstport; - verbosedebugf("Received Response from %#-15a addressed to %#-15a on %p with %2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s", + verbosedebugf("Received Response from %#-15a addressed to %#-15a on %p with " + "%2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s", srcaddr, dstaddr, InterfaceID, response->h.numQuestions, response->h.numQuestions == 1 ? ", " : "s,", response->h.numAnswers, response->h.numAnswers == 1 ? ", " : "s,", @@ -5487,9 +5587,7 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m, rr->DelayDelivery = m->timenow + mDNSPlatformOneSecond; // to delay delivery of this 'add' event else rr->DelayDelivery = CheckForSoonToExpireRecords(m, rr->resrec.name, rr->resrec.namehash, slot); - CacheRecordAdd(m, rr); - // MUST do this AFTER CacheRecordAdd(), because that's what sets CRActiveQuestion for us - SetNextCacheCheckTime(m, rr); + CacheRecordAdd(m, rr); // CacheRecordAdd calls SetNextCacheCheckTime(m, rr); for us } } } @@ -5511,13 +5609,20 @@ exit: for (r2 = cg ? cg->members : mDNSNULL; r2; r2=r2->next) if (SameResourceRecordSignature(&r1->resrec, &r2->resrec)) { - // If record is recent, just ensure the whole RRSet has the same TTL (as required by DNS semantics) - // else, if record is old, mark it to be flushed - if (m->timenow - r2->TimeRcvd < mDNSPlatformOneSecond) + // If record was recently positively received + // (i.e. not counting goodbye packets or cache flush events that set the TTL to 1) + // then we need to ensure the whole RRSet has the same TTL (as required by DNS semantics) + if (r2->resrec.rroriginalttl > 1 && m->timenow - r2->TimeRcvd < mDNSPlatformOneSecond) + { + if (r2->resrec.rroriginalttl != r1->resrec.rroriginalttl) + LogMsg("Correcting TTL from %4d to %4d for %s", + r2->resrec.rroriginalttl, r1->resrec.rroriginalttl, CRDisplayString(m, r2)); r2->resrec.rroriginalttl = r1->resrec.rroriginalttl; - else + r2->TimeRcvd = m->timenow; + } + else // else, if record is old, mark it to be flushed { - verbosedebugf("Cache flush %p X %p %##s (%s)", r1, r2, r2->resrec.name->c, DNSTypeName(r2->resrec.rrtype)); + verbosedebugf("Cache flush %p X %p %s", r1, r2, CRDisplayString(m, r2)); // We set stale records to expire in one second. // This gives the owner a chance to rescue it if necessary. // This is important in the case of multi-homing and bridged networks: @@ -5532,11 +5637,12 @@ exit: r2->resrec.rroriginalttl = 1; r2->TimeRcvd = m->timenow; r2->UnansweredQueries = MaxUnansweredQueries; - SetNextCacheCheckTime(m, r2); } + SetNextCacheCheckTime(m, r2); } if (r1->DelayDelivery) // If we were planning to delay delivery of this record, see if we still need to { + // Note, only need to call SetNextCacheCheckTime() when DelayDelivery is set, not when it's cleared r1->DelayDelivery = CheckForSoonToExpireRecords(m, r1->resrec.name, r1->resrec.namehash, slot); if (!r1->DelayDelivery) CacheRecordDeferredAdd(m, r1); } @@ -5555,9 +5661,7 @@ mDNSexport void mDNSCoreReceive(mDNS *const m, void *const pkt, const mDNSu8 *co const mDNSu8 UpdateR = kDNSFlag0_QR_Response | kDNSFlag0_OP_Update; #ifndef UNICAST_DISABLED - mDNSIPPort NATPort = mDNSOpaque16fromIntVal(NATMAP_PORT); - - if (srcport.NotAnInteger == NATPort.NotAnInteger) + if (srcport.NotAnInteger == NATPMPPort.NotAnInteger) { mDNS_Lock(m); uDNS_ReceiveNATMap(m, pkt, (mDNSu16)(end - (mDNSu8 *)pkt)); @@ -5693,17 +5797,15 @@ mDNSlocal mStatus mDNS_StartQuery_internal(mDNS *const m, DNSQuestion *const que return(mStatus_AlreadyRegistered); } - // If this question is referencing a specific interface, make sure it exists + // If this question is referencing a specific interface, verify it exists if (question->InterfaceID && question->InterfaceID != mDNSInterface_LocalOnly) { NetworkInterfaceInfo *intf; for (intf = m->HostInterfaces; intf; intf = intf->next) if (intf->InterfaceID == question->InterfaceID) break; if (!intf) - { - debugf("mDNS_StartQuery_internal: Question %##s InterfaceID %p not found", question->qname.c, question->InterfaceID); - return(mStatus_BadInterfaceErr); - } + LogMsg("Note: InterfaceID %p for question %##s not currently found in active interface list", + question->InterfaceID, question->qname.c); } if (!ValidateDomainName(&question->qname)) @@ -5718,32 +5820,35 @@ mDNSlocal mStatus mDNS_StartQuery_internal(mDNS *const m, DNSQuestion *const que // that we have *no* relevant answers currently in our cache, then it will accelerate that to go out immediately. if (!m->RandomQueryDelay) m->RandomQueryDelay = 1 + (mDNSs32)mDNSRandom((mDNSu32)InitialQuestionInterval); - question->next = mDNSNULL; - question->qnamehash = DomainNameHashValue(&question->qname); // MUST do this before FindDuplicateQuestion() - question->DelayAnswering = CheckForSoonToExpireRecords(m, &question->qname, question->qnamehash, HashSlot(&question->qname)); - question->ThisQInterval = InitialQuestionInterval * 2; // MUST be > zero for an active question - question->RequestUnicast = 2; // Set to 2 because is decremented once *before* we check it - question->LastQTime = m->timenow - m->RandomQueryDelay; // Avoid inter-machine synchronization - question->LastAnswerPktNum = m->PktNum; - question->RecentAnswerPkts = 0; - question->CurrentAnswers = 0; - question->LargeAnswers = 0; - question->UniqueAnswers = 0; - question->DuplicateOf = FindDuplicateQuestion(m, question); - question->NextInDQList = mDNSNULL; + question->next = mDNSNULL; + question->qnamehash = DomainNameHashValue(&question->qname); // MUST do this before FindDuplicateQuestion() + question->DelayAnswering = CheckForSoonToExpireRecords(m, &question->qname, question->qnamehash, HashSlot(&question->qname)); + question->ThisQInterval = InitialQuestionInterval * 2; // MUST be > zero for an active question + question->RequestUnicast = 2; // Set to 2 because is decremented once *before* we check it + question->LastQTime = m->timenow - m->RandomQueryDelay; // Avoid inter-machine synchronization + question->LastAnswerPktNum = m->PktNum; + question->RecentAnswerPkts = 0; + question->CurrentAnswers = 0; + question->LargeAnswers = 0; + question->UniqueAnswers = 0; + question->FlappingInterface = mDNSNULL; + question->DuplicateOf = FindDuplicateQuestion(m, question); + question->NextInDQList = mDNSNULL; for (i=0; iDupSuppress[i].InterfaceID = mDNSNULL; // question->InterfaceID must be already set by caller - question->SendQNow = mDNSNULL; - question->SendOnAll = mDNSfalse; - question->LastQTxTime = m->timenow; + question->SendQNow = mDNSNULL; + question->SendOnAll = mDNSfalse; + question->LastQTxTime = m->timenow; if (!question->DuplicateOf) verbosedebugf("mDNS_StartQuery_internal: Question %##s (%s) %p %d (%p) started", - question->qname.c, DNSTypeName(question->qtype), question->InterfaceID, question->LastQTime + question->ThisQInterval - m->timenow, question); + question->qname.c, DNSTypeName(question->qtype), question->InterfaceID, + question->LastQTime + question->ThisQInterval - m->timenow, question); else verbosedebugf("mDNS_StartQuery_internal: Question %##s (%s) %p %d (%p) duplicate of (%p)", - question->qname.c, DNSTypeName(question->qtype), question->InterfaceID, question->LastQTime + question->ThisQInterval - m->timenow, question, question->DuplicateOf); + question->qname.c, DNSTypeName(question->qtype), question->InterfaceID, + question->LastQTime + question->ThisQInterval - m->timenow, question, question->DuplicateOf); *q = question; if (question->InterfaceID == mDNSInterface_LocalOnly) @@ -5795,7 +5900,8 @@ mDNSlocal mStatus mDNS_StopQuery_internal(mDNS *const m, DNSQuestion *const ques for (q = m->Questions; q; q=q->next) // Scan our list of questions if (ActiveQuestion(q) && ResourceRecordAnswersQuestion(&rr->resrec, q)) break; - verbosedebugf("mDNS_StopQuery_internal: Cache RR %##s (%s) setting CRActiveQuestion to %p", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), q); + verbosedebugf("mDNS_StopQuery_internal: Cache RR %##s (%s) setting CRActiveQuestion to %p", + rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), q); rr->CRActiveQuestion = q; // Question used to be active; new value may or may not be null if (!q) m->rrcache_active--; // If no longer active, decrement rrcache_active count } @@ -6025,12 +6131,10 @@ mDNSlocal void FoundServiceInfo(mDNS *const m, DNSQuestion *question, const Reso if (query->ServiceInfoQueryCallback && query->GotTXT) { if (++query->Answers >= 100) - { - if (answer->rrtype == kDNSType_A) - debugf("**** WARNING **** have given %lu answers for %##s (A) %.4a", query->Answers, query->qSRV.qname.c, &answer->rdata->u.ipv4); - else - debugf("**** WARNING **** have given %lu answers for %##s (AAAA) %.16a", query->Answers, query->qSRV.qname.c, &answer->rdata->u.ipv6); - } + debugf(answer->rrtype == kDNSType_A ? + "**** WARNING **** have given %lu answers for %##s (A) %.4a" : + "**** WARNING **** have given %lu answers for %##s (AAAA) %.16a", + query->Answers, query->qSRV.qname.c, &answer->rdata->u.data); query->ServiceInfoQueryCallback(m, query); } } @@ -6172,7 +6276,10 @@ mDNSexport mStatus mDNS_Update(mDNS *const m, AuthRecord *const rr, mDNSu32 newt #endif if (!ValidateRData(rr->resrec.rrtype, newrdlength, newrdata)) - { LogMsg("Attempt to update record with invalid rdata: %s", GetRRDisplayString_rdb(&rr->resrec, &newrdata->u, m->MsgBuffer)); return(mStatus_Invalid); } + { + LogMsg("Attempt to update record with invalid rdata: %s", GetRRDisplayString_rdb(&rr->resrec, &newrdata->u, m->MsgBuffer)); + return(mStatus_Invalid); + } mDNS_Lock(m); @@ -6195,7 +6302,8 @@ mDNSexport mStatus mDNS_Update(mDNS *const m, AuthRecord *const rr, mDNSu32 newt if (unicast) { mStatus status = uDNS_UpdateRecord(m, rr); mDNS_Unlock(m); return(status); } - if (rr->resrec.rroriginalttl == newttl && rr->resrec.rdlength == newrdlength && mDNSPlatformMemSame(rr->resrec.rdata->u.data, newrdata->u.data, newrdlength)) + if (rr->resrec.rroriginalttl == newttl && + rr->resrec.rdlength == newrdlength && mDNSPlatformMemSame(rr->resrec.rdata->u.data, newrdata->u.data, newrdlength)) CompleteRDataUpdate(m, rr); else { @@ -6221,7 +6329,8 @@ mDNSexport mStatus mDNS_Update(mDNS *const m, AuthRecord *const rr, mDNSu32 newt if (!rr->UpdateBlocked) rr->UpdateBlocked = NonZeroTime(m->timenow + (mDNSs32)delay * mDNSPlatformOneSecond); rr->ThisAPInterval *= 4; rr->LastAPTime = rr->UpdateBlocked - rr->ThisAPInterval; - LogMsg("Excessive update rate for %##s; delaying announcement by %ld second%s", rr->resrec.name->c, delay, delay > 1 ? "s" : ""); + LogMsg("Excessive update rate for %##s; delaying announcement by %ld second%s", + rr->resrec.name->c, delay, delay > 1 ? "s" : ""); } rr->resrec.rroriginalttl = newttl; } @@ -6439,7 +6548,7 @@ mDNSlocal void UpdateInterfaceProtocols(mDNS *const m, NetworkInterfaceInfo *act } } -mDNSexport mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *set, mDNSs32 delay) +mDNSexport mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *set, mDNSBool flapping) { mDNSBool FirstOfType = mDNStrue; NetworkInterfaceInfo **p = &m->HostInterfaces; @@ -6452,11 +6561,12 @@ mDNSexport mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *s mDNS_Lock(m); - // Assume this interface will be active + // Assume this interface will be active now, unless we find a duplicate already in the list set->InterfaceActive = mDNStrue; set->IPv4Available = (set->ip.type == mDNSAddrType_IPv4 && set->McastTxRx); set->IPv6Available = (set->ip.type == mDNSAddrType_IPv6 && set->McastTxRx); + // Scan list to see if this InterfaceID is already represented while (*p) { if (*p == set) @@ -6466,9 +6576,9 @@ mDNSexport mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *s return(mStatus_AlreadyRegistered); } - // This InterfaceID is already in the list, so mark this interface inactive for now if ((*p)->InterfaceID == set->InterfaceID) { + // This InterfaceID already represented by a different interface in the list, so mark this instance inactive for now set->InterfaceActive = mDNSfalse; if (set->ip.type == (*p)->ip.type) FirstOfType = mDNSfalse; if (set->ip.type == mDNSAddrType_IPv4 && set->McastTxRx) (*p)->IPv4Available = mDNStrue; @@ -6484,12 +6594,12 @@ mDNSexport mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *s if (set->Advertise) AdvertiseInterface(m, set); - debugf("mDNS_RegisterInterface: InterfaceID %p %#a %s", set->InterfaceID, &set->ip, + LogOperation("mDNS_RegisterInterface: InterfaceID %p %s (%#a) %s", set->InterfaceID, set->ifname, &set->ip, set->InterfaceActive ? "not represented in list; marking active and retriggering queries" : "already represented in list; marking inactive for now"); - // In some versions of OS X the IPv6 address remains on an interface even when the interface is turned off, + // In early versions of OS X the IPv6 address remains on an interface even when the interface is turned off, // giving the false impression that there's an active representative of this interface when there really isn't. // Therefore, when registering an interface, we want to re-trigger our questions and re-probe our Resource Records, // even if we believe that we previously had an active representative of this interface. @@ -6497,28 +6607,39 @@ mDNSexport mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *s { DNSQuestion *q; AuthRecord *rr; - mDNSs32 initial = InitialQuestionInterval; + // If flapping, delay between first and second queries is eight seconds instead of one + mDNSs32 delay = flapping ? mDNSPlatformOneSecond * 5 : 0; + mDNSu8 announce = flapping ? (mDNSu8)1 : InitialAnnounceCount; // Use a small amount of randomness: - // In the case of a network administrator turning on an Ethernet hub so that all the connected machines establish link at - // exactly the same time, we don't want them to all go and hit the network with identical queries at exactly the same moment. + // In the case of a network administrator turning on an Ethernet hub so that all the + // connected machines establish link at exactly the same time, we don't want them all + // to go and hit the network with identical queries at exactly the same moment. if (!m->SuppressSending) m->SuppressSending = m->timenow + (mDNSs32)mDNSRandom((mDNSu32)InitialQuestionInterval); - if (delay) + if (flapping) { - LogMsg("Repeated transitions for interface %s (%#a); delaying packets by %d seconds", - set->ifname, &set->ip, delay/mDNSPlatformOneSecond); - initial = InitialQuestionInterval * 8; // Delay between first and second queries is eight seconds + LogMsg("Note: Frequent transitions for interface %s (%#a); network traffic reduction measures in effect", set->ifname, &set->ip); if (!m->SuppressProbes || m->SuppressProbes - (m->timenow + delay) < 0) m->SuppressProbes = (m->timenow + delay); } + for (q = m->Questions; q; q=q->next) // Scan our list of questions if (!q->InterfaceID || q->InterfaceID == set->InterfaceID) // If non-specific Q, or Q on this specific interface, { // then reactivate this question - q->ThisQInterval = initial; // MUST be > zero for an active question - q->RequestUnicast = 2; // Set to 2 because is decremented once *before* we check it - q->LastQTime = m->timenow - q->ThisQInterval + delay; + mDNSs32 initial = (flapping && q->FlappingInterface != set->InterfaceID) ? InitialQuestionInterval * 8 : InitialQuestionInterval; + mDNSs32 qdelay = (flapping && q->FlappingInterface != set->InterfaceID) ? mDNSPlatformOneSecond * 5 : 0; + if (flapping && q->FlappingInterface == set->InterfaceID) + LogOperation("No cache records for %##s (%s) expired; no need for immediate question", q->qname.c, DNSTypeName(q->qtype)); + + if (!q->ThisQInterval || q->ThisQInterval > initial) + { + q->ThisQInterval = initial; + q->RequestUnicast = 2; // Set to 2 because is decremented once *before* we check it + } + if (q->LastQTime - (m->timenow - q->ThisQInterval + qdelay) > 0) + q->LastQTime = (m->timenow - q->ThisQInterval + qdelay); q->RecentAnswerPkts = 0; SetNextQueryTime(m,q); } @@ -6530,7 +6651,7 @@ mDNSexport mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *s { if (rr->resrec.RecordType == kDNSRecordTypeVerified && !rr->DependentOn) rr->resrec.RecordType = kDNSRecordTypeUnique; rr->ProbeCount = DefaultProbeCountForRecordType(rr->resrec.RecordType); - rr->AnnounceCount = delay ? (mDNSu8)1 : InitialAnnounceCount; + if (rr->AnnounceCount < announce) rr->AnnounceCount = announce; rr->ThisAPInterval = DefaultAPIntervalForRecordType(rr->resrec.RecordType); InitializeLastAPTime(m, rr); } @@ -6543,7 +6664,7 @@ mDNSexport mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *s // NOTE: mDNS_DeregisterInterface calls mDNS_Deregister_internal which can call a user callback, which may change // the record list and/or question list. // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this. -mDNSexport void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *set) +mDNSexport void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *set, mDNSBool flapping) { NetworkInterfaceInfo **p = &m->HostInterfaces; @@ -6579,8 +6700,8 @@ mDNSexport void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *se break; if (intf) { - debugf("mDNS_DeregisterInterface: Another representative of InterfaceID %p exists; making it active", - set->InterfaceID); + LogOperation("mDNS_DeregisterInterface: Another representative of InterfaceID %p %s (%#a) exists;" + " making it active", set->InterfaceID, set->ifname, &set->ip); intf->InterfaceActive = mDNStrue; UpdateInterfaceProtocols(m, intf); @@ -6597,19 +6718,32 @@ mDNSexport void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *se CacheGroup *cg; CacheRecord *rr; DNSQuestion *q; - debugf("mDNS_DeregisterInterface: Last representative of InterfaceID %p deregistered; marking questions etc. dormant", - set->InterfaceID); + LogOperation("mDNS_DeregisterInterface: Last representative of InterfaceID %p %s (%#a) deregistered;" + " marking questions etc. dormant", set->InterfaceID, set->ifname, &set->ip); - // 1. Deactivate any questions specific to this interface + if (flapping) + LogMsg("Note: Frequent transitions for interface %s (%#a); network traffic reduction measures in effect", + set->ifname, &set->ip); + + // 1. Deactivate any questions specific to this interface, and tag appropriate questions + // so that mDNS_RegisterInterface() knows how swiftly it needs to reactivate them for (q = m->Questions; q; q=q->next) - if (q->InterfaceID == set->InterfaceID) - q->ThisQInterval = 0; + { + if (q->InterfaceID == set->InterfaceID) q->ThisQInterval = 0; + if (!q->InterfaceID || q->InterfaceID == set->InterfaceID) + q->FlappingInterface = set->InterfaceID; + } // 2. Flush any cache records received on this interface revalidate = mDNSfalse; // Don't revalidate if we're flushing the records FORALL_CACHERECORDS(slot, cg, rr) if (rr->resrec.InterfaceID == set->InterfaceID) - PurgeCacheResourceRecord(m, rr); + { + // If this interface is deemed flapping, + // postpone deleting the cache records in case the interface comes back again + if (!flapping) PurgeCacheResourceRecord(m, rr); + else mDNS_Reconfirm_internal(m, rr, kDefaultReconfirmTimeForFlappingInterface); + } } } @@ -6628,7 +6762,7 @@ mDNSexport void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *se m->NextCacheCheck = m->timenow; FORALL_CACHERECORDS(slot, cg, rr) if (rr->resrec.InterfaceID == set->InterfaceID) - mDNS_Reconfirm_internal(m, rr, kDefaultReconfirmTimeForCableDisconnect); + mDNS_Reconfirm_internal(m, rr, kDefaultReconfirmTimeForFlappingInterface); } mDNS_Unlock(m); @@ -6713,7 +6847,8 @@ mDNSexport mStatus mDNS_RegisterService(mDNS *const m, ServiceRecordSet *sr, else sr->Host.c[0] = 0; // If port number is zero, that means the client is really trying to do a RegisterNoSuchService - if (!port.NotAnInteger) return(mDNS_RegisterNoSuchService(m, &sr->RR_SRV, name, type, domain, mDNSNULL, mDNSInterface_Any, NSSCallback, sr)); + if (!port.NotAnInteger) + return(mDNS_RegisterNoSuchService(m, &sr->RR_SRV, name, type, domain, mDNSNULL, mDNSInterface_Any, NSSCallback, sr)); // Initialize the AuthRecord objects to sane values mDNS_SetupResourceRecord(&sr->RR_ADV, mDNSNULL, InterfaceID, kDNSType_PTR, kStandardTTL, kDNSRecordTypeAdvisory, ServiceCallback, sr); @@ -6822,7 +6957,8 @@ mDNSexport mStatus mDNS_AddRecordToService(mDNS *const m, ServiceRecordSet *sr, mStatus status; extra->next = mDNSNULL; - mDNS_SetupResourceRecord(&extra->r, rdata, sr->RR_PTR.resrec.InterfaceID, extra->r.resrec.rrtype, ttl, kDNSRecordTypeUnique, ServiceCallback, sr); + mDNS_SetupResourceRecord(&extra->r, rdata, sr->RR_PTR.resrec.InterfaceID, + extra->r.resrec.rrtype, ttl, kDNSRecordTypeUnique, ServiceCallback, sr); AssignDomainName(extra->r.resrec.name, sr->RR_SRV.resrec.name); #ifndef UNICAST_DISABLED @@ -6857,7 +6993,8 @@ mDNSexport mStatus mDNS_AddRecordToService(mDNS *const m, ServiceRecordSet *sr, return(status); } -mDNSexport mStatus mDNS_RemoveRecordFromService(mDNS *const m, ServiceRecordSet *sr, ExtraResourceRecord *extra, mDNSRecordCallback MemFreeCallback, void *Context) +mDNSexport mStatus mDNS_RemoveRecordFromService(mDNS *const m, ServiceRecordSet *sr, ExtraResourceRecord *extra, + mDNSRecordCallback MemFreeCallback, void *Context) { ExtraResourceRecord **e; mStatus status; @@ -6904,7 +7041,11 @@ mDNSexport mStatus mDNS_RenameAndReregisterService(mDNS *const m, ServiceRecordS IncrementLabelSuffix(&name2, mDNStrue); newname = &name2; } - LogMsg("Service \"%##s\" renamed to \"%#s\"", sr->RR_SRV.resrec.name->c, newname->c); + + if (SameDomainName(&domain, &localdomain)) + LogMsg("%##s service renamed from \"%#s\" to \"%#s\"", type.c, name1.c, newname->c); + else LogMsg("%##s service (domain %##s) renamed from \"%#s\" to \"%#s\"",type.c, domain.c, name1.c, newname->c); + if (sr->RR_SRV.HostTarget == mDNSfalse && sr->Host.c[0]) host = &sr->Host; err = mDNS_RegisterService(m, sr, newname, &type, &domain, @@ -7059,7 +7200,7 @@ mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p, m->p = p; m->KnownBugs = 0; - m->CanReceiveUnicastOn5353 = mDNSfalse; // Assume we can't receive unicasts on 5353, unless platform layer tells us otherwise + m->CanReceiveUnicastOn5353 = mDNSfalse; // Assume we can't receive unicasts on 5353, unless platform layer tells us otherwise m->AdvertiseLocalAddresses = AdvertiseLocalAddresses; m->mDNSPlatformStatus = mStatus_Waiting; m->UnicastPort4 = zeroIPPort; @@ -7092,6 +7233,7 @@ mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p, m->NextScheduledResponse = timenow + 0x78000000; m->ExpectUnicastResponse = timenow + 0x78000000; m->RandomQueryDelay = 0; + m->RandomReconfirmDelay = 0; m->PktNum = 0; m->SendDeregistrations = mDNSfalse; m->SendImmediateAnswers = mDNSfalse; diff --git a/mDNSCore/mDNSDebug.h b/mDNSCore/mDNSDebug.h index 0ff368f..591312b 100755 --- a/mDNSCore/mDNSDebug.h +++ b/mDNSCore/mDNSDebug.h @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: mDNSDebug.h,v $ +Revision 1.26.2.1 2006/08/29 06:24:22 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.26 2005/07/04 22:40:26 cheshire Additional debugging code to help catch memory corruption diff --git a/mDNSCore/mDNSEmbeddedAPI.h b/mDNSCore/mDNSEmbeddedAPI.h index 9f81dc8..4b4d8ae 100755 --- a/mDNSCore/mDNSEmbeddedAPI.h +++ b/mDNSCore/mDNSEmbeddedAPI.h @@ -1,24 +1,18 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ NOTE: @@ -60,6 +54,36 @@ Change History (most recent first): $Log: mDNSEmbeddedAPI.h,v $ +Revision 1.296.2.1 2006/08/29 06:24:22 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + +Revision 1.296 2006/06/29 05:28:01 cheshire +Added comment about mDNSlocal and mDNSexport + +Revision 1.295 2006/06/29 03:02:43 cheshire + mDNSResponder NXDOMAIN and CNAME support + +Revision 1.294 2006/06/28 06:50:08 cheshire +In future we may want to change definition of mDNSs32 from "signed long" to "signed int" +I doubt anyone is building mDNSResponder on systems where int is 16-bits, +but lets add a compile-time assertion to make sure. + +Revision 1.293 2006/06/12 18:00:43 cheshire +To make code a little more defensive, check _ILP64 before _LP64, +in case both are set by mistake on some platforms + +Revision 1.292 2006/03/19 17:00:57 cheshire +Define symbol MaxMsg instead of using hard-coded constant value '80' + +Revision 1.291 2006/03/19 02:00:07 cheshire + Improve logic for delaying packets after repeated interface transitions + +Revision 1.290 2006/03/08 22:42:23 cheshire +Fix spelling mistake: LocalReverseMapomain -> LocalReverseMapDomain + +Revision 1.289 2006/02/26 00:54:41 cheshire +Fixes to avoid code generation warning/error on FreeBSD 7 + Revision 1.288 2005/12/21 03:24:58 cheshire Code changes required to compile on EFI @@ -1033,6 +1057,19 @@ Merge in license terms from Quinn's copy, in preparation for Darwin release #define mDNSexport #endif +// Explanation: These local/export markers are a little habit of mine for signaling the programmers' intentions. +// When "mDNSlocal" is just a synonym for "static", and "mDNSexport" is a complete no-op, you could be +// forgiven for asking what purpose they serve. The idea is that if you see "mDNSexport" in front of a +// function definition it means the programmer intended it to be exported and callable from other files +// in the project. If you see "mDNSlocal" in front of a function definition it means the programmer +// intended it to be private to that file. If you see neither in front of a function definition it +// means the programmer forgot (so you should work out which it is supposed to be, and fix it). +// Using "mDNSlocal" instead of "static" makes it easier to do a textual searches for one or the other. +// For example you can do a search for "static" to find if any functions declare any local variables as "static" +// (generally a bad idea unless it's also "const", because static storage usually risks being non-thread-safe) +// without the results being cluttered with hundreds of matches for functions declared static. +// - Stuart Cheshire + // *************************************************************************** // Structure packing macro @@ -1118,15 +1155,17 @@ typedef unsigned short mDNSu16; // Macro Name __LP64__ Value 1 // A quick Google search for "defined(__LP64__)" OR "#ifdef __LP64__" gives 2590 hits and // a search for "#if __LP64__" gives only 12, so I think we'll go with the majority and use defined() -#if defined(_LP64) || defined(__LP64__) -typedef signed int mDNSs32; -typedef unsigned int mDNSu32; -#elif defined(_ILP64) || defined(__ILP64__) +#if defined(_ILP64) || defined(__ILP64__) typedef signed int32 mDNSs32; typedef unsigned int32 mDNSu32; +#elif defined(_LP64) || defined(__LP64__) +typedef signed int mDNSs32; +typedef unsigned int mDNSu32; #else typedef signed long mDNSs32; typedef unsigned long mDNSu32; +//typedef signed int mDNSs32; +//typedef unsigned int mDNSu32; #endif // To enforce useful type checking, we make mDNSInterfaceID be a pointer to a dummy struct @@ -1866,6 +1905,7 @@ struct DNSQuestion_struct mDNSu32 CurrentAnswers; // Number of records currently in the cache that answer this question mDNSu32 LargeAnswers; // Number of answers with rdata > 1024 bytes mDNSu32 UniqueAnswers; // Number of answers received with kDNSClass_UniqueRRSet bit set + mDNSInterfaceID FlappingInterface;// Set when an interface goes away, to flag if removes are delivered for this Q DNSQuestion *DuplicateOf; DNSQuestion *NextInDQList; DupSuppressInfo DupSuppress[DupSuppressInfoSize]; @@ -1886,6 +1926,7 @@ struct DNSQuestion_struct mDNSBool LongLived; // Set by client for calls to mDNS_StartQuery to indicate LLQs to unicast layer. mDNSBool ExpectUnique; // Set by client if it's expecting unique RR(s) for this question, not shared RRs mDNSBool ForceMCast; // Set by client to force mDNS query, even for apparently uDNS names + mDNSBool ReturnCNAME; // Set by client to request callbacks for intermediate CNAME records mDNSQuestionCallback *QuestionCallback; void *QuestionContext; }; @@ -1936,7 +1977,6 @@ struct ServiceInfoQuery_struct #define NATMAP_MAX_TRIES 3 // for max 3 tries #define NATMAP_DEFAULT_LEASE (60 * 60) // lease life in seconds #define NATMAP_VERS 0 -#define NATMAP_PORT 5351 #define NATMAP_RESPONSE_MASK 0x80 typedef enum @@ -2090,7 +2130,8 @@ struct mDNS_struct mDNSu8 lock_rrcache; // For debugging: Set at times when these lists may not be modified mDNSu8 lock_Questions; mDNSu8 lock_Records; - char MsgBuffer[80]; // Temp storage used while building error log messages + #define MaxMsg 120 + char MsgBuffer[MaxMsg]; // Temp storage used while building error log messages // Task Scheduling variables mDNSs32 timenow_adjust; // Correction applied if we ever discover time went backwards @@ -2104,6 +2145,7 @@ struct mDNS_struct mDNSs32 NextScheduledResponse; // Next time to send authoritative record(s) in responses mDNSs32 ExpectUnicastResponse; // Set when we send a query with the kDNSQClass_UnicastResponse bit set mDNSs32 RandomQueryDelay; // For de-synchronization of query packets on the wire + mDNSu32 RandomReconfirmDelay; // For de-synchronization of reconfirmation queries on the wire mDNSs32 PktNum; // Unique sequence number assigned to each received packet mDNSBool SendDeregistrations; // Set if we need to send deregistrations (immediately) mDNSBool SendImmediateAnswers; // Set if we need to send answers (immediately -- or as soon as SuppressSending clears) @@ -2169,10 +2211,14 @@ extern const mDNSInterfaceID mDNSInterface_Any; // Zero extern const mDNSInterfaceID mDNSInterface_LocalOnly; // Special value extern const mDNSIPPort UnicastDNSPort; +extern const mDNSIPPort NATPMPPort; +extern const mDNSIPPort DNSEXTPort; extern const mDNSIPPort MulticastDNSPort; +extern const mDNSIPPort LoopbackIPCPort; + extern const mDNSv4Addr AllDNSAdminGroup; -extern const mDNSv4Addr AllDNSLinkGroupv4; -extern const mDNSv6Addr AllDNSLinkGroupv6; +#define AllDNSLinkGroupv4 (AllDNSLinkGroup_v4.ip.v4) +#define AllDNSLinkGroupv6 (AllDNSLinkGroup_v6.ip.v6) extern const mDNSAddr AllDNSLinkGroup_v4; extern const mDNSAddr AllDNSLinkGroup_v6; @@ -2183,8 +2229,8 @@ extern const mDNSOpaque16 ResponseFlags; extern const mDNSOpaque16 UpdateReqFlags; extern const mDNSOpaque16 UpdateRespFlags; -#define localdomain (*(const domainname *)"\x5local") -#define LocalReverseMapomain (*(const domainname *)"\x3" "254" "\x3" "169" "\x7" "in-addr" "\x4" "arpa") +#define localdomain (*(const domainname *)"\x5" "local") +#define LocalReverseMapDomain (*(const domainname *)"\x3" "254" "\x3" "169" "\x7" "in-addr" "\x4" "arpa") // *************************************************************************** #if 0 @@ -2659,8 +2705,8 @@ extern mDNSs32 mDNSPlatformUTC (void); // Platform support modules should provide the following functions to map between opaque interface IDs // and interface indexes in order to support the DNS-SD API. If your target platform does not support // multiple interfaces and/or does not support the DNS-SD API, these functions can be empty. -extern mDNSInterfaceID mDNSPlatformInterfaceIDfromInterfaceIndex(const mDNS *const m, mDNSu32 index); -extern mDNSu32 mDNSPlatformInterfaceIndexfromInterfaceID(const mDNS *const m, mDNSInterfaceID id); +extern mDNSInterfaceID mDNSPlatformInterfaceIDfromInterfaceIndex(mDNS *const m, mDNSu32 index); +extern mDNSu32 mDNSPlatformInterfaceIndexfromInterfaceID(mDNS *const m, mDNSInterfaceID id); // Every platform support module must provide the following functions if it is to support unicast DNS // and Dynamic Update. @@ -2752,8 +2798,8 @@ extern mStatus LNT_UnmapPort(mDNSIPPort PubPort, mDNSBool tcp); // not lightweight second-by-second CPU power management modes.) extern void mDNS_SetFQDN(mDNS *const m); -extern mStatus mDNS_RegisterInterface (mDNS *const m, NetworkInterfaceInfo *set, mDNSs32 delay); -extern void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *set); +extern mStatus mDNS_RegisterInterface (mDNS *const m, NetworkInterfaceInfo *set, mDNSBool flapping); +extern void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *set, mDNSBool flapping); extern void mDNSCoreInitComplete(mDNS *const m, mStatus result); extern void mDNSCoreReceive(mDNS *const m, void *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr, const mDNSIPPort srcport, @@ -2790,6 +2836,7 @@ struct mDNS_CompileTimeAssertionChecks char assertA[(sizeof(mDNSOpaque32) == 4 ) ? 1 : -1]; char assertB[(sizeof(mDNSOpaque128) == 16 ) ? 1 : -1]; char assertC[(sizeof(CacheRecord ) >= sizeof(CacheGroup) ) ? 1 : -1]; + char assertD[(sizeof(int) >= 4 ) ? 1 : -1]; }; // *************************************************************************** diff --git a/mDNSCore/uDNS.c b/mDNSCore/uDNS.c index 2e7c354..20cdadb 100755 --- a/mDNSCore/uDNS.c +++ b/mDNSCore/uDNS.c @@ -1,28 +1,38 @@ -/* - * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved. +/* -*- Mode: C; tab-width: 4 -*- * - * @APPLE_LICENSE_HEADER_START@ + * Copyright (c) 2002-2006 Apple Computer, Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: uDNS.c,v $ +Revision 1.230.2.1 2006/08/29 06:24:23 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + +Revision 1.230 2006/06/29 03:02:44 cheshire + mDNSResponder NXDOMAIN and CNAME support + +Revision 1.229 2006/03/02 22:03:41 cheshire + Spurious warning "GetLargeResourceRecord: m->rec appears to be already in use" +Refinement: m->rec.r.resrec.RecordType needs to be cleared *every* time around for loop, not just once at the end + +Revision 1.228 2006/02/26 00:54:42 cheshire +Fixes to avoid code generation warning/error on FreeBSD 7 + +Revision 1.227 2006/01/09 20:47:05 cheshire + Spurious warning "GetLargeResourceRecord: m->rec appears to be already in use" + Revision 1.226 2005/12/20 02:46:33 cheshire mDNSPosix wide-area registration broken Check too strict -- we can still do wide-area registration (without NAT-PMP) @@ -951,7 +961,7 @@ mDNSexport void mDNS_AddDNSServer(mDNS *const m, const mDNSAddr *addr, const dom mDNS_Lock(m); if (!d) d = (domainname *)""; - while (*p) // Check if we already have this {server,domain} pair registered + while (*p) // Check if we already have this {server,domain} pair registered { if (mDNSSameAddress(&(*p)->addr, addr) && SameDomainName(&(*p)->domain, d)) LogMsg("Note: DNS Server %#a for domain %##s registered more than once", addr, d->c); @@ -1133,8 +1143,6 @@ mDNSlocal mDNSBool FreeNATInfo(mDNS *m, NATTraversalInfo *n) mDNSlocal void SendNATMsg(NATTraversalInfo *info, mDNS *m) { mStatus err; - mDNSAddr dst; - mDNSIPPort dstport; uDNS_GlobalInfo *u = &m->uDNS_info; if (info->state != NATState_Request && info->state != NATState_Refresh) @@ -1142,15 +1150,12 @@ mDNSlocal void SendNATMsg(NATTraversalInfo *info, mDNS *m) if (u->Router.ip.v4.NotAnInteger) { - // send msg if we have a router + // send msg if we have a router const mDNSu8 *end = (mDNSu8 *)&info->request; if (info->op == NATOp_AddrRequest) end += sizeof(NATAddrRequest); else end += sizeof(NATPortMapRequest); - dst.type = u->Router.type; - dst.ip.v4 = u->Router.ip.v4; - dstport = mDNSOpaque16fromIntVal(NATMAP_PORT); - err = mDNSPlatformSendUDP(m, &info->request, end, 0, &dst, dstport); + err = mDNSPlatformSendUDP(m, &info->request, end, 0, &u->Router, NATPMPPort); if (!err) (info->ntries++); // don't increment attempt counter if the send failed } @@ -2052,6 +2057,9 @@ mDNSlocal void deriveGoodbyes(mDNS * const m, DNSMessage *msg, const mDNSu8 *en m->mDNS_reentrancy++; // Increment to allow client to legally make mDNS API calls from the callback question->QuestionCallback(m, question, &ka->resrec, mDNSfalse); m->mDNS_reentrancy--; // Decrement to block mDNS API calls again + // CAUTION: Need to be careful after calling question->QuestionCallback(), + // because the client's callback function is allowed to do anything, + // including starting/stopping queries, registering/deregistering records, etc. if (question != m->uDNS_info.CurrentQuery) { debugf("deriveGoodbyes - question removed via callback. returning."); @@ -2097,6 +2105,9 @@ mDNSlocal void deriveGoodbyes(mDNS * const m, DNSMessage *msg, const mDNSu8 *en m->mDNS_reentrancy++; // Increment to allow client to legally make mDNS API calls from the callback question->QuestionCallback(m, question, &ka->resrec, mDNSfalse); m->mDNS_reentrancy--; // Decrement to block mDNS API calls again + // CAUTION: Need to be careful after calling question->QuestionCallback(), + // because the client's callback function is allowed to do anything, + // including starting/stopping queries, registering/deregistering records, etc. if (question != m->uDNS_info.CurrentQuery) { debugf("deriveGoodbyes - question removed via callback. returning."); @@ -2132,9 +2143,10 @@ mDNSlocal void pktResponseHndlr(mDNS * const m, DNSMessage *msg, const mDNSu8 * { const mDNSu8 *ptr; int i; - LargeCacheRecord lcr; - CacheRecord *cr = &lcr.r; - mDNSBool goodbye, inKAList, followedCName = mDNSfalse; + CacheRecord *cr = &m->rec.r; + mDNSBool goodbye, inKAList; + int followedCNames = 0; + static const int maxCNames = 5; LLQ_Info *llqInfo = question->uDNS_info.llq; domainname origname; origname.c[0] = 0; @@ -2142,6 +2154,40 @@ mDNSlocal void pktResponseHndlr(mDNS * const m, DNSMessage *msg, const mDNSu8 * if (question != m->uDNS_info.CurrentQuery) { LogMsg("ERROR: pktResponseHdnlr called without CurrentQuery ptr set!"); return; } + if (question->uDNS_info.Answered == 0 && msg->h.numAnswers == 0 && !llq) + { + /* NXDOMAIN error or empty RR set - notify client */ + question->uDNS_info.Answered = mDNStrue; + + /* Create empty resource record */ + cr->resrec.RecordType = kDNSRecordTypeUnregistered; + cr->resrec.InterfaceID = mDNSNULL; + cr->resrec.name = &question->qname; + cr->resrec.rrtype = question->qtype; + cr->resrec.rrclass = question->qclass; + cr->resrec.rroriginalttl = 1; /* What should we use for the TTL? TTL from SOA for domain? */ + cr->resrec.rdlength = 0; + cr->resrec.rdestimate = 0; + cr->resrec.namehash = 0; + cr->resrec.namehash = 0; + cr->resrec.rdata = (RData*)&cr->rdatastorage; + cr->resrec.rdata->MaxRDLength = cr->resrec.rdlength; + + /* Pass empty answer to callback */ + m->mDNS_reentrancy++; // Increment to allow client to legally make mDNS API calls from the callback + question->QuestionCallback(m, question, &cr->resrec, 0); + m->mDNS_reentrancy--; // Decrement to block mDNS API calls again + // CAUTION: Need to be careful after calling question->QuestionCallback(), + // because the client's callback function is allowed to do anything, + // including starting/stopping queries, registering/deregistering records, etc. + m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it + if (question != m->uDNS_info.CurrentQuery) + { + debugf("pktResponseHndlr - CurrentQuery changed by QuestionCallback - returning."); + return; + } + } + question->uDNS_info.Answered = mDNStrue; ptr = LocateAnswers(msg, end); @@ -2149,30 +2195,50 @@ mDNSlocal void pktResponseHndlr(mDNS * const m, DNSMessage *msg, const mDNSu8 * for (i = 0; i < msg->h.numAnswers; i++) { - ptr = GetLargeResourceRecord(m, msg, ptr, end, 0, kDNSRecordTypePacketAns, &lcr); + ptr = GetLargeResourceRecord(m, msg, ptr, end, 0, kDNSRecordTypePacketAns, &m->rec); if (!ptr) goto pkt_error; if (ResourceRecordAnswersQuestion(&cr->resrec, question)) { + goodbye = llq ? ((mDNSs32)cr->resrec.rroriginalttl == -1) : mDNSfalse; if (cr->resrec.rrtype == kDNSType_CNAME) { - if (followedCName) LogMsg("Error: multiple CNAME referals for question %##s", question->qname.c); + if (followedCNames > (maxCNames - 1)) LogMsg("Error: too many CNAME referals for question %##s", &origname); else { debugf("Following cname %##s -> %##s", question->qname.c, cr->resrec.rdata->u.name.c); + if (question->ReturnCNAME) + { + m->mDNS_reentrancy++; // Increment to allow client to legally make mDNS API calls from the callback + question->QuestionCallback(m, question, &cr->resrec, !goodbye); + m->mDNS_reentrancy--; // Decrement to block mDNS API calls again + // CAUTION: Need to be careful after calling question->QuestionCallback(), + // because the client's callback function is allowed to do anything, + // including starting/stopping queries, registering/deregistering records, etc. + if (question != m->uDNS_info.CurrentQuery) + { + m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it + debugf("pktResponseHndlr - CurrentQuery changed by QuestionCallback - returning."); + return; + } + } AssignDomainName(&origname, &question->qname); AssignDomainName(&question->qname, &cr->resrec.rdata->u.name); question->qnamehash = DomainNameHashValue(&question->qname); - followedCName = mDNStrue; + followedCNames++; i = -1; // restart packet answer matching ptr = LocateAnswers(msg, end); + m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it continue; } } - goodbye = llq ? ((mDNSs32)cr->resrec.rroriginalttl == -1) : mDNSfalse; inKAList = kaListContainsAnswer(question, cr); - if ((goodbye && !inKAList) || (!goodbye && inKAList)) continue; // list up to date + if ((goodbye && !inKAList) || (!goodbye && inKAList)) + { + m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it + continue; // list up to date + } if (!inKAList) addKnownAnswer(question, cr); if (goodbye) removeKnownAnswer(question, cr); m->mDNS_reentrancy++; // Increment to allow client to legally make mDNS API calls from the callback @@ -2180,16 +2246,15 @@ mDNSlocal void pktResponseHndlr(mDNS * const m, DNSMessage *msg, const mDNSu8 * m->mDNS_reentrancy--; // Decrement to block mDNS API calls again if (question != m->uDNS_info.CurrentQuery) { + m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it debugf("pktResponseHndlr - CurrentQuery changed by QuestionCallback - returning"); return; } } - else if (!followedCName || !SameDomainName(cr->resrec.name, &origname)) - LogMsg("Question %##s %X (%s) %##s unexpected answer %##s %X (%s)", - question->qname.c, question->qnamehash, DNSTypeName(question->qtype), origname.c, - cr->resrec.name->c, cr->resrec.namehash, DNSTypeName(cr->resrec.rrtype)); + + m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it } - + if (!llq || llqInfo->state == LLQ_Poll || llqInfo->deriveRemovesOnResume) { deriveGoodbyes(m, msg, end,question); @@ -2686,7 +2751,7 @@ mDNSlocal mDNSBool uDNS_ReceiveTestQuestionResponse(mDNS *const m, DNSMessage *c if (found && result == DNSServer_Failed) LogMsg("NOTE: Wide-Area Service Discovery disabled to avoid crashing defective DNS relay %#a.", srcaddr); - return(mDNStrue); // Return mDNStrue to tell uDNS_ReceiveMsg it doens't need to process this packet further + return(mDNStrue); // Return mDNStrue to tell uDNS_ReceiveMsg it doens't need to process this packet further } mDNSexport void uDNS_ReceiveMsg(mDNS *const m, DNSMessage *const msg, const mDNSu8 *const end, @@ -4620,7 +4685,7 @@ mDNSexport mStatus uDNS_AddRecordToService(mDNS *const m, ServiceRecordSet *sr, else { err = SetupRecordRegistration(m, &extra->r); - extra->r.uDNS_info.state = regState_ExtraQueued; // %%% Is it okay to overwrite the previous uDNS_info.state? + extra->r.uDNS_info.state = regState_ExtraQueued; // %%% Is it okay to overwrite the previous uDNS_info.state? } if (!err) @@ -4799,7 +4864,7 @@ mDNSlocal mDNSs32 CheckQueries(mDNS *m, mDNSs32 timenow) { sendtime = q->LastQTime + q->ThisQInterval; if (m->SuppressStdPort53Queries && - sendtime - m->SuppressStdPort53Queries < 0) // Don't allow sendtime to be earlier than SuppressStdPort53Queries + sendtime - m->SuppressStdPort53Queries < 0) // Don't allow sendtime to be earlier than SuppressStdPort53Queries sendtime = m->SuppressStdPort53Queries; if (sendtime - timenow < 0) { @@ -4939,7 +5004,7 @@ mDNSexport void uDNS_Execute(mDNS *const m) if (nexte - u->nextevent < 0) u->nextevent = nexte; if (m->SuppressStdPort53Queries && m->timenow - m->SuppressStdPort53Queries >= 0) - m->SuppressStdPort53Queries = 0; // If suppression time has passed, clear it + m->SuppressStdPort53Queries = 0; // If suppression time has passed, clear it nexte = CheckQueries(m, timenow); if (nexte - u->nextevent < 0) u->nextevent = nexte; diff --git a/mDNSCore/uDNS.h b/mDNSCore/uDNS.h index 6d86705..c7e0e7c 100755 --- a/mDNSCore/uDNS.h +++ b/mDNSCore/uDNS.h @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: uDNS.h,v $ +Revision 1.32.2.1 2006/08/29 06:24:23 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.32 2005/07/29 19:46:10 ksekar reduce polling period on failed LLQs to 15 minutes diff --git a/mDNSMacOS9/CarbonResource.r b/mDNSMacOS9/CarbonResource.r index 105a398..c7a49a0 100644 --- a/mDNSMacOS9/CarbonResource.r +++ b/mDNSMacOS9/CarbonResource.r @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: CarbonResource.r,v $ +Revision 1.6 2006/08/14 23:24:29 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.5 2003/08/12 19:56:24 cheshire Update to APSL 2.0 diff --git a/mDNSMacOS9/Mac OS Test Responder.c b/mDNSMacOS9/Mac OS Test Responder.c index 76a426c..cc14173 100644 --- a/mDNSMacOS9/Mac OS Test Responder.c +++ b/mDNSMacOS9/Mac OS Test Responder.c @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: Mac\040OS\040Test\040Responder.c,v $ +Revision 1.25 2006/08/14 23:24:29 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.24 2004/12/16 20:49:34 cheshire Cache memory management improvements diff --git a/mDNSMacOS9/Mac OS Test Searcher.c b/mDNSMacOS9/Mac OS Test Searcher.c index fd28def..ac7b7d4 100644 --- a/mDNSMacOS9/Mac OS Test Searcher.c +++ b/mDNSMacOS9/Mac OS Test Searcher.c @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: Mac\040OS\040Test\040Searcher.c,v $ +Revision 1.22 2006/08/14 23:24:29 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.21 2004/12/16 20:49:34 cheshire Cache memory management improvements diff --git a/mDNSMacOS9/Responder.c b/mDNSMacOS9/Responder.c index 2e7135e..7a1993f 100644 --- a/mDNSMacOS9/Responder.c +++ b/mDNSMacOS9/Responder.c @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: Responder.c,v $ +Revision 1.3 2006/08/14 23:24:29 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.2 2004/05/20 18:38:31 cheshire Fix build broken by removal of 'kDNSServiceFlagsAutoRename' from dns_sd.h diff --git a/mDNSMacOS9/Searcher.c b/mDNSMacOS9/Searcher.c index a0a562f..0e880c9 100644 --- a/mDNSMacOS9/Searcher.c +++ b/mDNSMacOS9/Searcher.c @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: Searcher.c,v $ +Revision 1.3 2006/08/14 23:24:29 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.2 2004/05/27 06:30:21 cheshire Add code to test DNSServiceQueryRecord() diff --git a/mDNSMacOS9/SubTypeTester.c b/mDNSMacOS9/SubTypeTester.c index 2206b22..d0eb613 100644 --- a/mDNSMacOS9/SubTypeTester.c +++ b/mDNSMacOS9/SubTypeTester.c @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: SubTypeTester.c,v $ +Revision 1.7 2006/08/14 23:24:29 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.6 2004/12/16 20:49:35 cheshire Cache memory management improvements diff --git a/mDNSMacOS9/mDNSLibrary.c b/mDNSMacOS9/mDNSLibrary.c index d385cb4..e54ab00 100644 --- a/mDNSMacOS9/mDNSLibrary.c +++ b/mDNSMacOS9/mDNSLibrary.c @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: mDNSLibrary.c,v $ +Revision 1.4 2006/08/14 23:24:29 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.3 2004/12/16 20:49:35 cheshire Cache memory management improvements diff --git a/mDNSMacOS9/mDNSLibraryLoader.c b/mDNSMacOS9/mDNSLibraryLoader.c index d671d77..f829f14 100644 --- a/mDNSMacOS9/mDNSLibraryLoader.c +++ b/mDNSMacOS9/mDNSLibraryLoader.c @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: mDNSLibraryLoader.c,v $ +Revision 1.2 2006/08/14 23:24:29 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.1 2004/03/12 21:30:26 cheshire Build a System-Context Shared Library from mDNSCore, for the benefit of developers like Muse Research who want to be able to use mDNS/DNS-SD from GPL-licensed code. diff --git a/mDNSMacOS9/mDNSLibraryResources.r b/mDNSMacOS9/mDNSLibraryResources.r index a518d9d..b3b37ac 100644 --- a/mDNSMacOS9/mDNSLibraryResources.r +++ b/mDNSMacOS9/mDNSLibraryResources.r @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: mDNSLibraryResources.r,v $ +Revision 1.31.2.1 2006/08/29 06:24:28 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.31 2005/03/15 02:14:14 cheshire mDNSResponder-107 diff --git a/mDNSMacOS9/mDNSMacOS9.c b/mDNSMacOS9/mDNSMacOS9.c index 0dbbe5e..24cf117 100644 --- a/mDNSMacOS9/mDNSMacOS9.c +++ b/mDNSMacOS9/mDNSMacOS9.c @@ -1,28 +1,28 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: mDNSMacOS9.c,v $ +Revision 1.46 2006/08/14 23:24:29 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + +Revision 1.45 2006/03/19 02:00:14 cheshire + Improve logic for delaying packets after repeated interface transitions + Revision 1.44 2005/09/16 21:06:50 cheshire Use mDNS_TimeNow_NoLock macro, instead of writing "mDNSPlatformRawTime() + m->timenow_adjust" all over the place @@ -406,7 +406,7 @@ mDNSlocal pascal void mDNSNotifier(void *contextPtr, OTEventCode code, OTResult case mOT_Bind: OTBind(m->p->ep, (TBind*)&mDNSbindReq, NULL); break; case mOT_Ready: mDNSinitComplete(m, mStatus_NoError); // Can't do mDNS_RegisterInterface until *after* mDNSinitComplete has set m->mDNSPlatformStatus to mStatus_NoError - mDNS_RegisterInterface(m, &m->p->interface, 0); + mDNS_RegisterInterface(m, &m->p->interface, mDNSfalse); break; default: LogMsg("Unexpected m->p->mOTstate %d", m->p->mOTstate-1); } @@ -423,7 +423,7 @@ mDNSlocal pascal void mDNSNotifier(void *contextPtr, OTEventCode code, OTResult if (m->p->mOTstate == mOT_Ready) { m->p->mOTstate = mOT_Closed; - mDNS_DeregisterInterface(m, &m->p->interface); + mDNS_DeregisterInterface(m, &m->p->interface, mDNSfalse); } if (m->p->ep) { OTCloseProvider(m->p->ep); m->p->ep = NULL; } break; // Do we need to do anything? @@ -645,7 +645,7 @@ extern void mDNSPlatformClose (mDNS *const m) if (m->p->mOTstate == mOT_Ready) { m->p->mOTstate = mOT_Closed; - mDNS_DeregisterInterface(m, &m->p->interface); + mDNS_DeregisterInterface(m, &m->p->interface, mDNSfalse); } if (m->p->ep) { OTCloseProvider (m->p->ep); m->p->ep = NULL; } if (m->p->OTTimerTask) { OTDestroyTimerTask(m->p->OTTimerTask); m->p->OTTimerTask = 0; } diff --git a/mDNSMacOS9/mDNSMacOS9.h b/mDNSMacOS9/mDNSMacOS9.h index c4fa310..149ec03 100755 --- a/mDNSMacOS9/mDNSMacOS9.h +++ b/mDNSMacOS9/mDNSMacOS9.h @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: mDNSMacOS9.h,v $ +Revision 1.11 2006/08/14 23:24:29 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.10 2004/03/12 21:30:26 cheshire Build a System-Context Shared Library from mDNSCore, for the benefit of developers like Muse Research who want to be able to use mDNS/DNS-SD from GPL-licensed code. diff --git a/mDNSMacOS9/mDNSPrefix.h b/mDNSMacOS9/mDNSPrefix.h index 80adab4..5cf83fb 100644 --- a/mDNSMacOS9/mDNSPrefix.h +++ b/mDNSMacOS9/mDNSPrefix.h @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: mDNSPrefix.h,v $ +Revision 1.4 2006/08/14 23:24:29 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.3 2004/06/11 00:03:28 cheshire Add code for testing avail/busy subtypes diff --git a/mDNSMacOSX/DNSServiceDiscoveryDefines.h b/mDNSMacOSX/DNSServiceDiscoveryDefines.h index c2f50c1..59bfd03 100644 --- a/mDNSMacOSX/DNSServiceDiscoveryDefines.h +++ b/mDNSMacOSX/DNSServiceDiscoveryDefines.h @@ -1,28 +1,25 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: DNSServiceDiscoveryDefines.h,v $ +Revision 1.7 2006/08/14 23:24:39 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.6 2004/09/20 21:45:27 ksekar Mach IPC cleanup diff --git a/mDNSMacOSX/DNSServiceDiscoveryReply.defs b/mDNSMacOSX/DNSServiceDiscoveryReply.defs index 942fb6b..b918bee 100644 --- a/mDNSMacOSX/DNSServiceDiscoveryReply.defs +++ b/mDNSMacOSX/DNSServiceDiscoveryReply.defs @@ -1,24 +1,18 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ */ subsystem diff --git a/mDNSMacOSX/DNSServiceDiscoveryRequest.defs b/mDNSMacOSX/DNSServiceDiscoveryRequest.defs index b6d9cf8..ad06bdb 100644 --- a/mDNSMacOSX/DNSServiceDiscoveryRequest.defs +++ b/mDNSMacOSX/DNSServiceDiscoveryRequest.defs @@ -1,24 +1,18 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ */ subsystem diff --git a/mDNSMacOSX/LegacyNATTraversal.c b/mDNSMacOSX/LegacyNATTraversal.c index 3816d58..371b6fc 100644 --- a/mDNSMacOSX/LegacyNATTraversal.c +++ b/mDNSMacOSX/LegacyNATTraversal.c @@ -2,33 +2,23 @@ * * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: LegacyNATTraversal.c,v $ -Revision 1.14 2005/12/08 03:00:33 cheshire - Byte order bugs in Legacy NAT traversal code - -Revision 1.13 2005/09/07 18:23:05 ksekar - Off-by-one overflow in LegacyNATTraversal +Revision 1.12.2.1 2006/08/29 06:24:30 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 Revision 1.12 2005/07/22 21:36:16 ksekar Fix GCC 4.0/Intel compiler warnings @@ -112,8 +102,6 @@ Revision 1.1 2004/08/18 17:35:41 ksekar // TODO: remove later and do variable length #define MAX_SOAPMSGSIZE 65536 -// This code accidentally closes fd 0 all over the place -// To stop that messing up the mDNSResponder core, we trap it and prevent it static int safe_close(int fd) { if (fd < 3) { /* LogMsg("safe_close: ERROR sd %d < 3", fd); */ return(-1); } @@ -122,10 +110,6 @@ static int safe_close(int fd) #define close safe_close -// This code uses fprintf(stderr, ...) and similar to log error messages -// We redirect all of them to syslog using our LogMsg mechanism -#define fprintf(file, ...) LogMsg(__VA_ARGS__) - //////////////////////////////////////////////////////////////////////// // NetAddr Functions //////////////////////////////////////////////////////////////////////// @@ -448,7 +432,7 @@ typedef struct tagIPINFO { int iFlags; char szIfName[IFNAMELEN]; /* Interface name */ - unsigned char abIP[IPLEN]; + unsigned char abIP[IPLEN]; /* IP in host byte order */ unsigned short wPort; } IPINFO, *PIPINFO, **PPIPINFO; @@ -456,13 +440,10 @@ typedef struct hostent HOSTENT, *PHOSTENT; static unsigned long GetNATIPNetmask(unsigned long dwIP) { - static const union { uint8_t b[4]; uint32_t l; } mask_10 = { { 255, 0, 0, 0 } }; // Mask for 10/8 - static const union { uint8_t b[4]; uint32_t l; } mask172 = { { 255, 240, 0, 0 } }; // Mask for 172.16/12 - static const union { uint8_t b[4]; uint32_t l; } mask192 = { { 255, 255, 0, 0 } }; // Mask for 192.168/16 - uint8_t *p = (uint8_t *)&dwIP; - if (p[0] == 10 ) return mask_10.l; - if (p[0] == 172 && (p[1] & 0xF0) == 16) return mask172.l; - if (p[0] == 192 && p[1] == 168 ) return mask192.l; + if ((dwIP & 0xFF000000) == 0x0A000000) return 0xFF000000; + if ((dwIP & 0xFFF00000) == 0xAC100000) return 0xFFF00000; + if ((dwIP & 0xFFFF0000) == 0xC0a80000) return 0xFFFF0000; + return 0; /* No NAT IP */ } @@ -546,7 +527,8 @@ static int GetIPInfo(PPIPINFO ppIPInfo) { case AF_INET: memcpy(pIPInfo[iNum].szIfName, ifr->ifr_name, IFNAMELEN); - dwIP = ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr.s_addr; + dwIP = + ntohl(((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr.s_addr); memcpy(pIPInfo[iNum].abIP, &dwIP, sizeof(unsigned long)); if (ifrcopy.ifr_flags & IFF_POINTOPOINT) pIPInfo[iNum].iFlags |= ISPPP; @@ -619,7 +601,7 @@ static int SSDPListen() saddr.sin_family = AF_INET; //saddr.sin_addr.s_addr = inet_addr(SSDP_IP); //saddr.sin_port = htons(SSDP_PORT); - saddr.sin_addr.s_addr = g_dwLocalIP; + saddr.sin_addr.s_addr = htonl(g_dwLocalIP); saddr.sin_port = 0; // and set the multicast add_member structure @@ -664,7 +646,7 @@ static int EventListen() bzero(&saddr, sizeof(saddr)); saddr.sin_len = sizeof(saddr); saddr.sin_family = AF_INET; - saddr.sin_addr.s_addr = g_dwLocalIP; + saddr.sin_addr.s_addr = htonl(g_dwLocalIP); saddr.sin_port = htons(g_wEventPort); // return if okay @@ -735,7 +717,7 @@ static void DumpHex(char *buf, int len) nexti = i + 16; endj = (nexti > len) ? len : nexti; for (j = i; j < endj; j++) - fprintf(g_log, "%02x %c ", buf[j] & 0xff, buf[j]); + fprintf(g_log, "%02x ", buf[j] & 0xff); if (j == len) { if ((j % 16) != 0) { char pad[3 * 16 + 1]; // don't need the last 3 bytes anyway @@ -774,7 +756,7 @@ static char *FindHTTPHeaderNewLine(char *pbuf, int iBufSize, int *pfEOH) result = memchr(pbuf, '\r', iBufSize); if (result == NULL) { if (g_fLogging & NALOG_INFO0) { - fprintf(g_log, "FindHTTPHeaderNewLine: er @(%d/%d)\n", i, iBufSize); + fprintf(g_log, "FindHTTPHeaderNewLine: er @(%d)\n", i); fflush(g_log); } return NULL; @@ -912,15 +894,7 @@ static PHTTPResponse NewHTTPResponse_sz( pszEOL = FindHTTPHeaderNewLine(pszEOL, iBufferSize - (pszEOL - pBuf), // remainder size &fEOH); - if (pszEOL == NULL) { - if (g_fLogging & NALOG_INFO0) { - fprintf(g_log, "NewHTTPResponse_sz: er reading header field %d @ %lu / %lu\n", - iNumHeaders, pHeader->pszName - pBuf, iBufferSize); - DumpHex(pszHTTPResponse, iBufferSize); - fflush(g_log); - } - goto cleanup; // syntax error - } + if (pszEOL == NULL) goto cleanup; // syntax error *pszEOL = '\0'; // terminate this string pszEOL += 2; // point to beginning of next line @@ -1330,9 +1304,12 @@ static void *TCPProc(void *in) char response[2000]; PHTTPResponse resp; int n; - sprintf(callback, "%u.%u.%u.%u:%u", - ((uint8_t*)&g_dwLocalIP)[0], ((uint8_t*)&g_dwLocalIP)[1], - ((uint8_t*)&g_dwLocalIP)[2], ((uint8_t*)&g_dwLocalIP)[3], g_wEventPort); + sprintf(callback, "%lu.%lu.%lu.%lu:%u", + (g_dwLocalIP >> 24) & 0xFF, + (g_dwLocalIP >> 16) & 0xFF, + (g_dwLocalIP >> 8) & 0xFF, + (g_dwLocalIP >> 0) & 0xFF, + g_wEventPort); n = sprintf((char *)buf, szEventMsgSubscribeFMT, @@ -1347,7 +1324,7 @@ static void *TCPProc(void *in) if (n > 0) { response[n] = '\0'; - resp = NewHTTPResponse_sz((char *)response, n+1, TRUE); + resp = NewHTTPResponse_sz((char *)buf, n, TRUE); if (NULL != resp) { ////TracePrint(ELL_TRACE, "UPnP Subscribe returns %s/%d\n", resp->pszStatus, n); @@ -1523,7 +1500,7 @@ static void *UDPProc(void *in) if (!FD_ISSET(g_sUDP, &readfds)) continue; recvaddrlen = sizeof(recvaddr); - n = recvfrom(g_sUDP, buf, sizeof(buf)-1, 0, + n = recvfrom(g_sUDP, buf, sizeof(buf), 0, (struct sockaddr *)&recvaddr, &recvaddrlen); if (n < 0) { if (g_fLogging & NALOG_ERROR) @@ -1536,7 +1513,7 @@ static void *UDPProc(void *in) } buf[n] = '\0'; if (strncmp((char *)buf, "HTTP/1.1", 8) == 0) { - PHTTPResponse pResponse = NewHTTPResponse_sz((char *)buf, n+1, TRUE); + PHTTPResponse pResponse = NewHTTPResponse_sz((char *)buf, n, TRUE); PrintHTTPResponse(pResponse); if (DiscoverRouter(pResponse) == 0) { @@ -1555,7 +1532,7 @@ static void *UDPProc(void *in) // temporarily use this to fudge - will have the exact same // parsing, only status/reason set to "*" and "HTTP/1.1". // TODO: add support for HTTP requests - PHTTPResponse pResponse = NewHTTPResponse_sz((char *)buf, n+1, TRUE); + PHTTPResponse pResponse = NewHTTPResponse_sz((char *)buf, n, TRUE); if (DiscoverRouter(pResponse) == 0) { time_t now = time(NULL); @@ -1877,14 +1854,13 @@ GetTimeElapsed(&tv_start, &tv_end, &tv_elapsed); FD_ZERO(&readfds); FD_SET(s, &readfds); - - // In testing, the Linksys Wireless-G Broadband Router "WRT54GS" takes - // up to four seconds to respond, and even then only a partial response, - // with the remainder coming in a second TCP segment half a second later. - // Accordingly, we wait up to five seconds for the initial data, and then after that - // wait one second after subsequent TCP segments, in care more data is still coming. - timeout.tv_sec = iBufLen ? 1 : 5; + //timeout.tv_sec = g_iFunctionTimeout / U_TOGRAN; + //timeout.tv_usec = (g_iFunctionTimeout % U_TOGRAN) * 1000000 / U_TOGRAN; + // just do flat 2 sec now, since connection already established + timeout.tv_sec = 1; timeout.tv_usec = 0; + + iRet = select(s+1, &readfds, NULL, NULL, &timeout); if (iRet <= 0) { @@ -1949,7 +1925,7 @@ GetTimeElapsed(&tv_start, &tv_end, &tv_elapsed); //fprintf(stderr, "2 -- \n"); if (g_fLogging & NALOG_INFO1) - fprintf(g_log, "SendTCPMsg_saddr_2part done recv %d @ %lu\n", iBufLen, time(NULL)); + fprintf(g_log, "done recv @%lu\n", time(NULL)); if (result == NULL) { // if caller just want to send/display msgs if (g_fLogging & NALOG_DUMP) @@ -2038,7 +2014,7 @@ static int SendTCPMsg_saddr_parse( } if (g_fLogging & NALOG_INFO1) - fprintf(g_log, "SendTCPMsg_saddr_parse: Before Sending TCP Msg: %d == %lu?\n", + fprintf(g_log, "SendTCPMsg/parse: Before Sending TCP Msg: %d == %lu?\n", iLen, strlen(msg)); if (g_fLogging & NALOG_DUMP) fprintf(g_log,"Sending TCP msg:\n[%s]\n", msg); @@ -2090,14 +2066,12 @@ static int SendTCPMsg_saddr_parse( FD_ZERO(&readfds); FD_SET(s, &readfds); - - // In testing, the Linksys Wireless-G Broadband Router "WRT54GS" takes - // up to four seconds to respond, and even then only a partial response, - // with the remainder coming in a second TCP segment half a second later. - // Accordingly, we wait up to five seconds for the initial data, and then after that - // wait one second after subsequent TCP segments, in care more data is still coming. - timeout.tv_sec = iBufLen ? 1 : 5; + //timeout.tv_sec = g_iFunctionTimeout / U_TOGRAN; + //timeout.tv_usec = (g_iFunctionTimeout % U_TOGRAN) * 1000000 / U_TOGRAN; + // just do flat 2 sec now, since connection already established + timeout.tv_sec = 1; timeout.tv_usec = 0; + iRet = select(s+1, &readfds, NULL, NULL, &timeout); if (iRet <= 0) { //fprintf(stderr, "**********: select failed (%d/%d)\n", iRet, errno); @@ -2124,8 +2098,6 @@ static int SendTCPMsg_saddr_parse( if (resultSize <= iBufLen) { char t[1000]; i = recv(s, &t, 1000, 0); - if (g_fLogging & NALOG_INFO1) - fprintf(g_log, "SendTCPMsg_saddr_parse discarding %d bytes\n", i); if (i== 0) break; // Note that there's no dump here - prevents DoS attack from // flooding the logs/diskspace @@ -2133,8 +2105,6 @@ static int SendTCPMsg_saddr_parse( } i = recv(s, result + iBufLen, resultSize - iBufLen, 0); - if (g_fLogging & NALOG_INFO1) - fprintf(g_log, "SendTCPMsg_saddr_parse read %d bytes (%d/%d)\n", i, iBufLen, resultSize); if (0 == i) { break; @@ -2157,7 +2127,7 @@ static int SendTCPMsg_saddr_parse( //fprintf(stderr, "p -- \n"); if (g_fLogging & NALOG_INFO1) - fprintf(g_log, "SendTCPMsg_saddr_parse done recv %d @ %lu\n", iBufLen, time(NULL)); + fprintf(g_log, "done recv @%lu\n", time(NULL)); if (result == NULL) { // if caller just want to send/display msgs if (g_fLogging & NALOG_DUMP) @@ -2269,8 +2239,6 @@ static PHTTPResponse SendSOAPMsgControlAction( &g_saddrRouterSOAP); } - if (g_fLogging & NALOG_INFO1) - fprintf(g_log, "SendSOAPMsgControlAction iResultLen %d\n", iResultLen); if (iResultLen > 0) { if (iResultLen > MAX_SOAPMSGSIZE) { if (g_fLogging & NALOG_ALERT) @@ -2501,8 +2469,10 @@ static void ParseURL( szBuf, pszHostPort?pszHostPort:"", pszPath?pszPath:"", - ((uint8_t*)&psaddr->sin_addr.s_addr)[0], ((uint8_t*)&psaddr->sin_addr.s_addr)[1], - ((uint8_t*)&psaddr->sin_addr.s_addr)[2], ((uint8_t*)&psaddr->sin_addr.s_addr)[3], + (psaddr->sin_addr.s_addr >> 24) & 0xff, + (psaddr->sin_addr.s_addr >> 16) & 0xff, + (psaddr->sin_addr.s_addr >> 8) & 0xff, + (psaddr->sin_addr.s_addr >> 0) & 0xff, psaddr->sin_port); #endif } @@ -2632,13 +2602,17 @@ static void GetIPByName(char *hostname, unsigned long *ip_ret) if (pHEnt == NULL) { if (g_fLogging & NALOG_ALERT) fprintf(g_log, "Can't translate [%s] to IP...\n", hostname); - g_dwLocalIP = INADDR_ANY; + g_dwLocalIP = htonl(INADDR_ANY); return; } - ip = *(unsigned long *)(pHEnt->h_addr); + ip = ntohl(*(unsigned long *)(pHEnt->h_addr)); if (g_fLogging & NALOG_INFO1) - fprintf(g_log, "hostname [%s] to ip: %u.%u.%u.%u\n", hostname, - ((uint8_t*)&ip)[0], ((uint8_t*)&ip)[1], ((uint8_t*)&ip)[2], ((uint8_t*)&ip)[3]); + fprintf(g_log, "hostname [%s] to ip: %ld.%ld.%ld.%ld\n", + hostname, + (ip >> 24) & 0xff, + (ip >> 16) & 0xff, + (ip >> 8) & 0xff, + (ip >> 0) & 0xff); } *ip_ret = ip; } @@ -2706,8 +2680,9 @@ mStatus LNT_UnmapPort(mDNSIPPort PubPort, mDNSBool tcp) //unsigned long dwIP; Property propArgs[3]; PHTTPResponse resp; + unsigned short port = PubPort.NotAnInteger; int protocol = tcp ? IPPROTO_TCP : IPPROTO_UDP; - sprintf(szEPort, "%u", mDNSVal16(PubPort)); + sprintf(szEPort, "%u", port); bzero(propArgs, sizeof(propArgs)); propArgs[0].pszName = "NewRemoteHost"; @@ -2755,19 +2730,26 @@ extern mStatus LNT_MapPort(mDNSIPPort priv, mDNSIPPort pub, mDNSBool tcp) char descr[40]; Property propArgs[8]; PHTTPResponse resp; + unsigned short iport = priv.NotAnInteger; + unsigned short eport = pub.NotAnInteger; int protocol = tcp ? IPPROTO_TCP : IPPROTO_UDP; - if (NA_E_EXISTS == GetMappingUnused(mDNSVal16(pub), protocol)) + + if (NA_E_EXISTS == GetMappingUnused(eport, protocol)) return mStatus_AlreadyRegistered; //DeletePortMapping(eport, protocol); - sprintf(szEPort, "%u", mDNSVal16(pub)); - sprintf(szIPort, "%u", mDNSVal16(priv)); + sprintf(szEPort, "%u", eport); + + sprintf(szIPort, "%u", iport); dwIP = g_dwLocalIP; sprintf(szLocalIP, "%u.%u.%u.%u", - ((uint8_t*)&dwIP)[0], ((uint8_t*)&dwIP)[1], ((uint8_t*)&dwIP)[2], ((uint8_t*)&dwIP)[3]); + (unsigned int)((dwIP >> 24) & 0xff), + (unsigned int)((dwIP >> 16) & 0xff), + (unsigned int)((dwIP >> 8) & 0xff), + (unsigned int)((dwIP >> 0) & 0xff)); bzero(propArgs, sizeof(propArgs)); propArgs[0].pszName = "NewRemoteHost"; @@ -2797,7 +2779,7 @@ extern mStatus LNT_MapPort(mDNSIPPort priv, mDNSIPPort pub, mDNSBool tcp) propArgs[5].pszValue = "1"; propArgs[5].pszType = "boolean"; propArgs[6].pszName = "NewPortMappingDescription"; - sprintf(descr, "iC%u", mDNSVal16(pub)); + sprintf(descr, "iC%u", eport); //propArgs[6].pszValue = "V"; propArgs[6].pszValue = descr; propArgs[6].pszType = "string"; @@ -2805,15 +2787,9 @@ extern mStatus LNT_MapPort(mDNSIPPort priv, mDNSIPPort pub, mDNSBool tcp) propArgs[7].pszValue = "0"; propArgs[7].pszType = "ui4"; - if (g_fLogging & NALOG_INFO1) - fprintf(g_log, "Sending AddPortMapping priv %u pub %u\n", mDNSVal16(priv), mDNSVal16(pub)); - resp = SendSOAPMsgControlAction( "AddPortMapping", 8, propArgs, FALSE); - if (g_fLogging & NALOG_INFO1) - fprintf(g_log, "AddPortMapping resp %p\n", resp); - if (resp == NULL) { return mStatus_NATTraversal; } @@ -2934,13 +2910,11 @@ int LegacyNATInit(void) pthread_attr_t attr; int iRet; //struct timeval tv; - LogOperation("LegacyNATInit"); static int fFirstInitLocks = TRUE; FILE *log = NULL; g_fLogging = 0; - //g_fLogging = ~0; // Turns ALL logging on g_log = stderr; SetLocalIP(); diff --git a/mDNSMacOSX/PreferencePane/BonjourPref.icns b/mDNSMacOSX/PreferencePane/BonjourPref.icns index 97b560f..5ba4674 100644 Binary files a/mDNSMacOSX/PreferencePane/BonjourPref.icns and b/mDNSMacOSX/PreferencePane/BonjourPref.icns differ diff --git a/mDNSMacOSX/PreferencePane/ConfigurationRights.h b/mDNSMacOSX/PreferencePane/ConfigurationRights.h index 85f441e..9e59fa5 100644 --- a/mDNSMacOSX/PreferencePane/ConfigurationRights.h +++ b/mDNSMacOSX/PreferencePane/ConfigurationRights.h @@ -45,7 +45,11 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Change History (most recent first): + $Log: ConfigurationRights.h,v $ +Revision 1.2 2006/08/14 23:15:47 cheshire +Tidy up Change History comment + Revision 1.1 2005/02/05 01:59:19 cheshire Add Preference Pane to facilitate testing of DDNS & wide-area features diff --git a/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.h b/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.h index 21f98f5..cf69c9c 100644 --- a/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.h +++ b/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.h @@ -41,7 +41,11 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Change History (most recent first): + $Log: DNSServiceDiscoveryPref.h,v $ +Revision 1.6 2006/08/14 23:15:47 cheshire +Tidy up Change History comment + Revision 1.5 2005/02/26 00:44:24 cheshire Restore default reg domain if user deletes text and clicks "apply" diff --git a/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.m b/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.m index e774498..373e52e 100644 --- a/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.m +++ b/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.m @@ -41,7 +41,14 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Change History (most recent first): + $Log: DNSServiceDiscoveryPref.m,v $ +Revision 1.8 2006/08/14 23:15:47 cheshire +Tidy up Change History comment + +Revision 1.7 2006/07/14 03:59:14 cheshire +Fix compile warnings: 'sortUsingFunction:context:' comparison function needs to return int + Revision 1.6 2005/02/26 00:44:24 cheshire Restore default reg domain if user deletes text and clicks "apply" @@ -70,14 +77,14 @@ Add Preference Pane to facilitate testing of DDNS & wide-area features @implementation DNSServiceDiscoveryPref -static CFComparisonResult +static int MyArrayCompareFunction(id val1, id val2, void *context) { return CFStringCompare((CFStringRef)val1, (CFStringRef)val2, kCFCompareCaseInsensitive); } -static CFComparisonResult +static int MyDomainArrayCompareFunction(id val1, id val2, void *context) { NSString *domain1 = [val1 objectForKey:(NSString *)SC_DYNDNS_DOMAIN_KEY]; @@ -1200,5 +1207,4 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query) [self disableControls]; } - -@end \ No newline at end of file +@end diff --git a/mDNSMacOSX/PreferencePane/English.lproj/InfoPlist.strings b/mDNSMacOSX/PreferencePane/English.lproj/InfoPlist.strings index e76e125..c523f4e 100644 Binary files a/mDNSMacOSX/PreferencePane/English.lproj/InfoPlist.strings and b/mDNSMacOSX/PreferencePane/English.lproj/InfoPlist.strings differ diff --git a/mDNSMacOSX/PreferencePane/PrivilegedOperations.c b/mDNSMacOSX/PreferencePane/PrivilegedOperations.c index 89b9736..0ca00db 100644 --- a/mDNSMacOSX/PreferencePane/PrivilegedOperations.c +++ b/mDNSMacOSX/PreferencePane/PrivilegedOperations.c @@ -41,7 +41,17 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Change History (most recent first): + $Log: PrivilegedOperations.c,v $ +Revision 1.6 2006/08/14 23:15:47 cheshire +Tidy up Change History comment + +Revision 1.5 2006/06/10 02:07:11 mkrochma +Whoa. Make sure code compiles before checking it in. + +Revision 1.4 2006/05/27 02:32:38 mkrochma +Wait for installer script to exit before returning result + Revision 1.3 2005/06/04 04:50:00 cheshire ddnswriteconfig (Bonjour PreferencePane) vulnerability Use installtool instead of requiring ddnswriteconfig to self-install @@ -132,8 +142,18 @@ OSStatus EnsureToolInstalled(void) { char *installerargs[] = { toolSourcePath, NULL }; err = AuthorizationExecuteWithPrivileges(authRef, toolInstallerPath, 0, installerargs, (FILE**) NULL); - if (err == noErr) - gToolApproved = true; + if (err == noErr) { + int status; + int pid = wait(&status); + if (pid > 0 && WIFEXITED(status)) { + err = WEXITSTATUS(status); + if (err == noErr) { + gToolApproved = true; + } + } else { + err = -1; + } + } (void) AuthorizationFree(authRef, kAuthorizationFlagDestroyRights); } } diff --git a/mDNSMacOSX/PreferencePane/PrivilegedOperations.h b/mDNSMacOSX/PreferencePane/PrivilegedOperations.h index c5c68a0..e76cb68 100644 --- a/mDNSMacOSX/PreferencePane/PrivilegedOperations.h +++ b/mDNSMacOSX/PreferencePane/PrivilegedOperations.h @@ -41,7 +41,11 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Change History (most recent first): + $Log: PrivilegedOperations.h,v $ +Revision 1.5 2006/08/14 23:15:47 cheshire +Tidy up Change History comment + Revision 1.4 2005/06/04 04:50:00 cheshire ddnswriteconfig (Bonjour PreferencePane) vulnerability Use installtool instead of requiring ddnswriteconfig to self-install diff --git a/mDNSMacOSX/PreferencePane/ddnswriteconfig.m b/mDNSMacOSX/PreferencePane/ddnswriteconfig.m index ff3080e..3c5398b 100644 --- a/mDNSMacOSX/PreferencePane/ddnswriteconfig.m +++ b/mDNSMacOSX/PreferencePane/ddnswriteconfig.m @@ -43,7 +43,11 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Change History (most recent first): + $Log: ddnswriteconfig.m,v $ +Revision 1.5 2006/08/14 23:15:47 cheshire +Tidy up Change History comment + Revision 1.4 2005/06/04 04:47:47 cheshire ddnswriteconfig (Bonjour PreferencePane) vulnerability Remove self-installing capability of ddnswriteconfig diff --git a/mDNSMacOSX/PreferencePane/installtool b/mDNSMacOSX/PreferencePane/installtool index 8fa79ad..6240d33 100755 --- a/mDNSMacOSX/PreferencePane/installtool +++ b/mDNSMacOSX/PreferencePane/installtool @@ -1,4 +1,5 @@ #!/usr/bin/perl +# Emacs settings: -*- tab-width: 4 -*- # # File: installtool # @@ -44,6 +45,12 @@ # Change History (most recent first): # # $Log: installtool,v $ +# Revision 1.3 2006/09/05 20:00:13 cheshire +# Moved Emacs settings to second line of file +# +# Revision 1.2 2006/08/14 23:15:14 cheshire +# Added "tab-width" emacs header line +# # Revision 1.1 2005/06/04 04:51:48 cheshire # ddnswriteconfig (Bonjour PreferencePane) vulnerability # Added separate "installtool" script instead of making ddnswriteconfig self-install diff --git a/mDNSMacOSX/SamplemDNSClient.c b/mDNSMacOSX/SamplemDNSClient.c index a387269..1e03989 100644 --- a/mDNSMacOSX/SamplemDNSClient.c +++ b/mDNSMacOSX/SamplemDNSClient.c @@ -1,24 +1,18 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ * * Formatting notes: * This code follows the "Whitesmiths style" C indentation rules. Plenty of discussion @@ -36,6 +30,12 @@ Change History (most recent first): $Log: SamplemDNSClient.c,v $ +Revision 1.48 2006/08/14 23:24:39 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + +Revision 1.47 2006/01/10 02:29:22 cheshire + Cosmetic IPv6 address display problem in mDNS test tool + Revision 1.46 2004/11/02 01:32:34 cheshire Update code so it still compiles when DNSServiceDiscovery.h is deprecated @@ -217,12 +217,14 @@ static void resolve_reply(struct sockaddr *interface, struct sockaddr *address, else if (address->sa_family == AF_INET6) { struct sockaddr_in6 *ip6 = (struct sockaddr_in6 *)address; - u_int16_t *w = ip6->sin6_addr.__u6_addr.__u6_addr16; + u_int8_t *b = ip6->sin6_addr.__u6_addr.__u6_addr8; union { uint16_t s; u_char b[2]; } port = { ip6->sin6_port }; uint16_t PortAsNumber = ((uint16_t)port.b[0]) << 8 | port.b[1]; char ipstring[40]; char ifname[IF_NAMESIZE + 1] = ""; - sprintf(ipstring, "%04X:%04X:%04X:%04X:%04X:%04X:%04X:%04X", w[0], w[1], w[2], w[3], w[4], w[5], w[6], w[7]); + sprintf(ipstring, "%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X", + b[0x0], b[0x1], b[0x2], b[0x3], b[0x4], b[0x5], b[0x6], b[0x7], + b[0x8], b[0x9], b[0xA], b[0xB], b[0xC], b[0xD], b[0xE], b[0xF]); if (ip6->sin6_scope_id) { ifname[0] = '%'; if_indextoname(ip6->sin6_scope_id, &ifname[1]); } printf("%s%s:%u", ipstring, ifname, PortAsNumber); } diff --git a/mDNSMacOSX/daemon.c b/mDNSMacOSX/daemon.c index d2b1b16..dab0a30 100644 --- a/mDNSMacOSX/daemon.c +++ b/mDNSMacOSX/daemon.c @@ -1,24 +1,18 @@ -/* - * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. +/* -*- Mode: C; tab-width: 4 -*- * - * @APPLE_LICENSE_HEADER_START@ + * Copyright (c) 2002-2006 Apple Computer, Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ * * Formatting notes: * This code follows the "Whitesmiths style" C indentation rules. Plenty of discussion @@ -36,6 +30,24 @@ Change History (most recent first): $Log: daemon.c,v $ +Revision 1.265.2.1 2006/08/29 06:24:30 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + +Revision 1.265 2006/06/29 07:32:08 cheshire +Added missing LogOperation logging for DNSServiceBrowse results + +Revision 1.264 2006/06/29 05:33:30 cheshire + mDNSResponder conditional compilation options + +Revision 1.263 2006/06/08 23:23:48 cheshire +Fix errant indentation of curly brace at the end of provide_DNSServiceBrowserCreate_rpc() + +Revision 1.262 2006/03/18 21:49:11 cheshire +Added comment in ShowTaskSchedulingError(mDNS *const m) + +Revision 1.261 2006/01/06 01:22:28 cheshire + Reword "mach_absolute_time went backwards" dialog + Revision 1.260 2005/11/07 01:51:58 cheshire Include list of configured DNS servers in SIGINFO output @@ -769,7 +781,8 @@ mDNSexport void LogMemCorruption(const char *format, ...) buffer[mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr)] = 0; va_end(ptr); LogMsg("!!!! %s !!!!", buffer); - NotifyOfElusiveBug("Memory Corruption", 0, buffer); + NotifyOfElusiveBug("Memory Corruption", buffer); + //*(long*)0 = -1; // Trick to crash and get a stack trace right here, if that's what we want } mDNSlocal void validatelists(mDNS *const m) @@ -1210,6 +1223,9 @@ mDNSlocal void FoundInstance(mDNS *const m, DNSQuestion *question, const Resourc DNSServiceBrowserResult **p = &browser->results; while (*p) p = &(*p)->next; *p = x; + + LogOperation("%5d: DNSServiceBrowse(%##s, %s) RESULT %s %s", + browser->ClientMachPort, question->qname.c, DNSTypeName(question->qtype), AddRecord ? "Add" : "Rmv", RRDisplayString(m, answer)); } mDNSlocal mStatus AddDomainToBrowser(DNSServiceBrowser *browser, const domainname *d) @@ -1259,8 +1275,10 @@ mDNSexport void DefaultBrowseDomainChanged(const domainname *d, mDNSBool add) *q = (*q)->next; if (remove->q.LongLived) { - // give goodbyes for known answers. note that since events are sent to client via udns_execute(), - // we don't need to worry about the question being cancelled mid-loop + // Give goodbyes for known answers. + // Note that this a special case where we know that the QuestionCallback function is our own + // code (it's FoundInstance), and that callback routine doesn't ever cancel its operation, so we + // don't need to guard against the question being cancelled mid-loop the way the mDNSCore routines do. CacheRecord *ka = remove->q.uDNS_info.knownAnswers; while (ka) { remove->q.QuestionCallback(&mDNSStorage, &remove->q, &ka->resrec, mDNSfalse); ka = ka->next; } } @@ -1351,7 +1369,7 @@ fail: LogMsg("%5d: DNSServiceBrowse(\"%s\", \"%s\") failed: %s (%ld)", client, regtype, domain, errormsg, err); if (SearchDomains) mDNS_FreeDNameList(SearchDomains); return(err); - } + } //************************************************************************************************************* // Resolve Service Info @@ -1770,13 +1788,15 @@ fail: return(err); } -mDNSlocal CFUserNotificationRef gNotification = NULL; -mDNSlocal CFRunLoopSourceRef gNotificationRLS = NULL; mDNSlocal domainlabel gNotificationPrefHostLabel; // The prefs as they were the last time we saw them mDNSlocal domainlabel gNotificationPrefNiceLabel; mDNSlocal domainlabel gNotificationUserHostLabel; // The prefs as they were the last time the user changed them mDNSlocal domainlabel gNotificationUserNiceLabel; +#ifndef NO_CFUSERNOTIFICATION +mDNSlocal CFUserNotificationRef gNotification = NULL; +mDNSlocal CFRunLoopSourceRef gNotificationRLS = NULL; + mDNSlocal void NotificationCallBackDismissed(CFUserNotificationRef userNotification, CFOptionFlags responseFlags) { (void)responseFlags; // Unused @@ -1821,6 +1841,7 @@ mDNSlocal void ShowNameConflictNotification(CFStringRef header, CFStringRef subt CFRelease(dictionary); } +#endif /* NO_CFUSERNOTIFICATION */ // This updates either the text of the field currently labelled "Local Hostname", // or the text of the field currently labelled "Computer Name" @@ -1857,6 +1878,7 @@ mDNSlocal void RecordUpdatedName(const mDNS *const m, const domainlabel *const o LogMsg("RecordUpdatedName: ERROR: Couldn't update SCPreferences"); else if (m->p->NotifyUser) { +#ifndef NO_CFUSERNOTIFICATION uid_t uid; gid_t gid; CFStringRef userName = SCDynamicStoreCopyConsoleUser(NULL, &uid, &gid); @@ -1874,6 +1896,9 @@ mDNSlocal void RecordUpdatedName(const mDNS *const m, const domainlabel *const o append(alertHeader, CFSTR("automatically.")); ShowNameConflictNotification(alertHeader, subtext); } +#else + (void)subtext; +#endif /* NO_CFUSERNOTIFICATION */ } if (s0) CFRelease(s0); if (s1) CFRelease(s1); @@ -1906,9 +1931,11 @@ mDNSlocal void mDNS_StatusCallback(mDNS *const m, mStatus result) { gNotificationUserHostLabel = gNotificationPrefHostLabel = m->p->userhostlabel; gNotificationUserNiceLabel = gNotificationPrefNiceLabel = m->p->usernicelabel; +#ifndef NO_CFUSERNOTIFICATION // If we're showing a name conflict notification, and the user has manually edited // the name to remedy the conflict, we should now remove the notification window. if (gNotificationRLS) CFUserNotificationCancel(gNotification); +#endif /* NO_CFUSERNOTIFICATION */ } DNSServiceRegistration *r; @@ -2568,6 +2595,8 @@ mDNSlocal void ShowTaskSchedulingError(mDNS *const m) LogMsg("Task Scheduling Error: Continuously busy for more than a second"); + // NOTE: To accurately diagnose *why* we're busy, the debugging code here to show needs to mirror the logic in GetNextScheduledEvent + if (m->NewQuestions && (!m->NewQuestions->DelayAnswering || m->timenow - m->NewQuestions->DelayAnswering >= 0)) LogMsg("Task Scheduling Error: NewQuestion %##s (%s)", m->NewQuestions->qname.c, DNSTypeName(m->NewQuestions->qtype)); diff --git a/mDNSMacOSX/mDNSMacOSX.c b/mDNSMacOSX/mDNSMacOSX.c index d926cb1..982192f 100644 --- a/mDNSMacOSX/mDNSMacOSX.c +++ b/mDNSMacOSX/mDNSMacOSX.c @@ -2,28 +2,54 @@ * * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: mDNSMacOSX.c,v $ +Revision 1.333.2.1 2006/08/29 06:24:30 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + +Revision 1.333 2006/06/29 05:33:30 cheshire + mDNSResponder conditional compilation options + +Revision 1.332 2006/06/28 09:10:36 cheshire +Extra debugging messages + +Revision 1.331 2006/06/21 22:29:42 cheshire +Make _CFCopySystemVersionDictionary() call more defensive on systems that have no build information set + +Revision 1.330 2006/06/20 23:06:00 cheshire +Fix some keychain API type mismatches (was mDNSu32 instead of UInt32) + +Revision 1.329 2006/06/08 23:22:33 cheshire +Comment changes + +Revision 1.328 2006/03/19 03:27:49 cheshire + Suppress "interface flapping" logic for loopback + +Revision 1.327 2006/03/19 02:00:09 cheshire + Improve logic for delaying packets after repeated interface transitions + +Revision 1.326 2006/03/08 22:42:23 cheshire +Fix spelling mistake: LocalReverseMapomain -> LocalReverseMapDomain + +Revision 1.325 2006/01/10 00:39:17 cheshire +Add comments explaining how IPv6 link-local addresses sometimes have an embedded scope_id + +Revision 1.324 2006/01/09 19:28:59 cheshire + Cap number of "sendto failed" messages we allow mDNSResponder to log + Revision 1.323 2006/01/05 21:45:27 cheshire Fix uninitialized structure member in IPv6 code @@ -1015,7 +1041,9 @@ Minor code tidying #include // For IPTOS_LOWDELAY etc. #include // For IN6_IFF_NOTREADY etc. +#ifndef NO_SECURITYFRAMEWORK #include +#endif /* NO_SECURITYFRAMEWORK */ #include "dnsinfo.h" @@ -1075,6 +1103,14 @@ mDNSlocal void SetSCPrefsBrowseDomain(mDNS *m, const domainname *d, mDNSBool add // *************************************************************************** // Functions +// We only attempt to send and receive multicast packets on interfaces that are +// (a) flagged as multicast-capable +// (b) *not* flagged as point-to-point (e.g. modem) +// Typically point-to-point interfaces are modems (including mobile-phone pseudo-modems), and we don't want +// to run up the user's bill sending multicast traffic over a link where there's only a single device at the +// other end, and that device (e.g. a modem bank) is probably not answering Multicast DNS queries anyway. +#define MulticastInterface(i) ((i->ifa_flags & IFF_MULTICAST) && !(i->ifa_flags & IFF_POINTOPOINT)) + // routines to allow access to default domain lists from daemon layer mDNSexport DNameListElem *mDNSPlatformGetSearchDomainList(void) @@ -1131,6 +1167,7 @@ mDNSlocal void RemoveDefRegDomain(domainname *d) debugf("Requested removal of default registration domain %##s not in contained in list", d->c); } +#ifndef NO_CFUSERNOTIFICATION mDNSexport void NotifyOfElusiveBug(const char *title, const char *msg) // Both strings are UTF-8 text { static int notifyCount = 0; @@ -1164,6 +1201,11 @@ mDNSexport void NotifyOfElusiveBug(const char *title, const char *msg) // Both s CFStringRef alertMessage = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@\r\r%@"), alertBody, alertFooter); CFUserNotificationDisplayNotice(0.0, kCFUserNotificationStopAlertLevel, NULL, NULL, NULL, alertHeader, alertMessage, NULL); } +#else +mDNSexport void NotifyOfElusiveBug(__unused const char *title, __unused const char *msg) + { + } +#endif /* NO_CFUSERNOTIFICATION */ mDNSlocal struct ifaddrs* myGetIfAddrs(int refresh) { @@ -1201,26 +1243,42 @@ mDNSlocal int myIfIndexToName(u_short index, char* name) return -1; } -mDNSexport mDNSInterfaceID mDNSPlatformInterfaceIDfromInterfaceIndex(const mDNS *const m, mDNSu32 index) +mDNSexport mDNSInterfaceID mDNSPlatformInterfaceIDfromInterfaceIndex(mDNS *const m, mDNSu32 index) { NetworkInterfaceInfoOSX *i; if (index == kDNSServiceInterfaceIndexLocalOnly) return(mDNSInterface_LocalOnly); - if (index) - for (i = m->p->InterfaceList; i; i = i->next) - // Don't get tricked by inactive interfaces with no InterfaceID set - if (i->ifinfo.InterfaceID && i->scope_id == index) return(i->ifinfo.InterfaceID); + if (index == kDNSServiceInterfaceIndexAny ) return(mDNSNULL); + + // Don't get tricked by inactive interfaces with no InterfaceID set + for (i = m->p->InterfaceList; i; i = i->next) + if (i->ifinfo.InterfaceID && i->scope_id == index) return(i->ifinfo.InterfaceID); + + // Not found. Make sure our interface list is up to date, then try again. + LogOperation("InterfaceID for interface index %d not found; Updating interface list", index); + mDNSMacOSXNetworkChanged(m); + for (i = m->p->InterfaceList; i; i = i->next) + if (i->ifinfo.InterfaceID && i->scope_id == index) return(i->ifinfo.InterfaceID); + return(mDNSNULL); } -mDNSexport mDNSu32 mDNSPlatformInterfaceIndexfromInterfaceID(const mDNS *const m, mDNSInterfaceID id) +mDNSexport mDNSu32 mDNSPlatformInterfaceIndexfromInterfaceID(mDNS *const m, mDNSInterfaceID id) { NetworkInterfaceInfoOSX *i; if (id == mDNSInterface_LocalOnly) return(kDNSServiceInterfaceIndexLocalOnly); - if (id) - for (i = m->p->InterfaceList; i; i = i->next) - // Don't use i->ifinfo.InterfaceID here, because we DO want to find inactive interfaces, which have no InterfaceID set - if ((mDNSInterfaceID)i == id) return(i->scope_id); - return 0; + if (id == mDNSInterface_Any ) return(0); + + // Don't use i->ifinfo.InterfaceID here, because we DO want to find inactive interfaces, which have no InterfaceID set + for (i = m->p->InterfaceList; i; i = i->next) + if ((mDNSInterfaceID)i == id) return(i->scope_id); + + // Not found. Make sure our interface list is up to date, then try again. + LogOperation("Interface index for InterfaceID %p not found; Updating interface list", id); + mDNSMacOSXNetworkChanged(m); + for (i = m->p->InterfaceList; i; i = i->next) + if ((mDNSInterfaceID)i == id) return(i->scope_id); + + return(0); } mDNSlocal mDNSBool AddrRequiresPPPConnection(const struct sockaddr *addr) @@ -1291,9 +1349,9 @@ mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const ms return mStatus_BadParamErr; } - // Don't send if it would cause dial on demand connection initiation. As an optimization, - // don't bother consulting reachability API / routing table when sending Multicast DNS - // since we ignore PPP interfaces for mDNS traffic + // Don't send if it would cause dial-on-demand connection initiation. + // As an optimization, don't bother consulting reachability API / routing + // table when sending Multicast DNS since we ignore PPP interfaces for mDNS traffic. if (!mDNSAddrIsDNSMulticast(dst) && AddrRequiresPPPConnection((struct sockaddr *)&to)) { debugf("mDNSPlatformSendUDP: Surpressing sending to avoid dial-on-demand connection"); @@ -1314,6 +1372,7 @@ mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const ms err = sendto(s, msg, (UInt8*)end - (UInt8*)msg, 0, (struct sockaddr *)&to, to.ss_len); if (err < 0) { + static int MessageCount = 0; // Don't report EHOSTDOWN (i.e. ARP failure), ENETDOWN, or no route to host for unicast destinations if (!mDNSAddressIsAllDNSLinkGroup(dst)) if (errno == EHOSTDOWN || errno == ENETDOWN || errno == EHOSTUNREACH || errno == ENETUNREACH) return(mStatus_TransientErr); @@ -1323,8 +1382,12 @@ mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const ms if (errno == EHOSTUNREACH && (mDNSu32)(mDNSPlatformRawTime()) < (mDNSu32)(mDNSPlatformOneSecond * 180)) return(mStatus_TransientErr); // Don't report EADDRNOTAVAIL ("Can't assign requested address") if we're in the middle of a network configuration change if (errno == EADDRNOTAVAIL && m->p->NetworkChanged) return(mStatus_TransientErr); - LogMsg("mDNSPlatformSendUDP sendto failed to send packet on InterfaceID %p %5s/%ld to %#a:%d skt %d error %d errno %d (%s) %lu", - InterfaceID, ifa_name, dst->type, dst, mDNSVal16(dstPort), s, err, errno, strerror(errno), (mDNSu32)(m->timenow)); + if (MessageCount < 1000) + { + MessageCount++; + LogMsg("mDNSPlatformSendUDP sendto failed to send packet on InterfaceID %p %5s/%ld to %#a:%d skt %d error %d errno %d (%s) %lu", + InterfaceID, ifa_name, dst->type, dst, mDNSVal16(dstPort), s, err, errno, strerror(errno), (mDNSu32)(m->timenow)); + } return(mStatus_UnknownErr); } @@ -1463,6 +1526,7 @@ mDNSlocal void myCFSocketCallBack(const CFSocketRef cfs, const CFSocketCallBackT senderAddr.type = mDNSAddrType_IPv6; senderAddr.ip.v6 = *(mDNSv6Addr*)&sin6->sin6_addr; senderPort.NotAnInteger = sin6->sin6_port; + //LogOperation("myCFSocketCallBack received IPv6 packet from %#a to %#a", &senderAddr, &destAddr); } else { @@ -1597,7 +1661,7 @@ mDNSexport mStatus mDNSPlatformTCPConnect(const mDNSAddr *dst, mDNSOpaque16 dstp saddr.sin_len = sizeof(saddr); memcpy(&saddr.sin_addr, &dst->ip.v4.NotAnInteger, sizeof(saddr.sin_addr)); - // Don't send if it would cause dial on demand connection initiation. + // Don't send if it would cause dial-on-demand connection initiation. if (AddrRequiresPPPConnection((struct sockaddr *)&saddr)) { debugf("mDNSPlatformTCPConnect: Surpressing sending to avoid dial-on-demand connection"); @@ -1955,8 +2019,8 @@ mDNSlocal mStatus SetupSocket(mDNS *const m, CFSocketSet *cp, mDNSBool mcast, co err = setsockopt(skt, IPPROTO_IPV6, IPV6_HOPLIMIT, &on, sizeof(on)); if (err < 0) { errstr = "setsockopt - IPV6_HOPLIMIT"; goto fail; } - // We want to receive only IPv6 packets, without this option, we may - // get IPv4 addresses as mapped addresses. + // We want to receive only IPv6 packets. Without this option we get IPv4 packets too, + // with mapped addresses of the form 0:0:0:0:0:FFFF:xxxx:xxxx, where xxxx:xxxx is the IPv4 address err = setsockopt(skt, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)); if (err < 0) { errstr = "setsockopt - IPV6_V6ONLY"; goto fail; } @@ -1965,6 +2029,7 @@ mDNSlocal mStatus SetupSocket(mDNS *const m, CFSocketSet *cp, mDNSBool mcast, co // Add multicast group membership on this interface, if it's for multicast receiving int interface_id = if_nametoindex(cp->info->ifa_name); struct ipv6_mreq i6mr; + //LogOperation("SetupSocket: v6 %#a %s %d", ifaddr, cp->info->ifa_name, interface_id); i6mr.ipv6mr_interface = interface_id; i6mr.ipv6mr_multiaddr = *(struct in6_addr*)&AllDNSLinkGroupv6; err = setsockopt(skt, IPPROTO_IPV6, IPV6_JOIN_GROUP, &i6mr, sizeof(i6mr)); @@ -2044,8 +2109,13 @@ mDNSlocal mStatus SetupAddr(mDNSAddr *ip, const struct sockaddr *const sa) if (sa->sa_family == AF_INET6) { struct sockaddr_in6 *ifa_addr = (struct sockaddr_in6 *)sa; - ip->type = mDNSAddrType_IPv6; + // Inside the BSD kernel they use a hack where they stuff the sin6->sin6_scope_id + // value into the second word of the IPv6 link-local address, so they can just + // pass around IPv6 address structures instead of full sockaddr_in6 structures. + // Those hacked IPv6 addresses aren't supposed to escape the kernel in that form, but they do. + // To work around this we always whack the second word of any IPv6 link-local address back to zero. if (IN6_IS_ADDR_LINKLOCAL(&ifa_addr->sin6_addr)) ifa_addr->sin6_addr.__u6_addr.__u6_addr16[1] = 0; + ip->type = mDNSAddrType_IPv6; ip->ip.v6 = *(mDNSv6Addr*)&ifa_addr->sin6_addr; return(mStatus_NoError); } @@ -2078,6 +2148,10 @@ mDNSlocal mDNSEthAddr GetBSSID(char *ifa_name) return(eth); } +// Returns pointer to newly created NetworkInterfaceInfoOSX object, or +// pointer to already-existing NetworkInterfaceInfoOSX object found in list, or +// may return NULL if out of memory (unlikely) or parameters are invalid for some reason +// (e.g. sa_family not AF_INET or AF_INET6) mDNSlocal NetworkInterfaceInfoOSX *AddInterfaceToList(mDNS *const m, struct ifaddrs *ifa, mDNSs32 utc) { mDNSu32 scope_id = if_nametoindex(ifa->ifa_name); @@ -2093,6 +2167,8 @@ mDNSlocal NetworkInterfaceInfoOSX *AddInterfaceToList(mDNS *const m, struct ifad { debugf("AddInterfaceToList: Found existing interface %lu %.6a with address %#a at %p", scope_id, &bssid, &ip, *p); (*p)->Exists = mDNStrue; + // If interface was not in getifaddrs list last time we looked, but it is now, update 'AppearanceTime' for this record + if ((*p)->LastSeen != utc) (*p)->AppearanceTime = utc; return(*p); } @@ -2114,11 +2190,14 @@ mDNSlocal NetworkInterfaceInfoOSX *AddInterfaceToList(mDNS *const m, struct ifad i->next = mDNSNULL; i->Exists = mDNStrue; + i->AppearanceTime = utc; // Brand new interface; AppearanceTime is now i->LastSeen = utc; + i->Flashing = mDNSfalse; + i->Occulting = mDNSfalse; i->scope_id = scope_id; i->BSSID = bssid; i->sa_family = ifa->ifa_addr->sa_family; - i->Multicast = (ifa->ifa_flags & IFF_MULTICAST) && !(ifa->ifa_flags & IFF_POINTOPOINT); + i->ifa_flags = ifa->ifa_flags; i->ss.m = m; i->ss.info = i; @@ -2149,8 +2228,10 @@ mDNSlocal mStatus UpdateInterfaceList(mDNS *const m, mDNSs32 utc) struct ifaddrs *v6Loopback = NULL; mDNSEthAddr PrimaryMAC = zeroEthAddr; char defaultname[32]; +#ifndef NO_IPV6 int InfoSocket = socket(AF_INET6, SOCK_DGRAM, 0); if (InfoSocket < 3) LogMsg("UpdateInterfaceList: InfoSocket error %d errno %d (%s)", InfoSocket, errno, strerror(errno)); +#endif if (m->SleepState) ifa = NULL; while (ifa) @@ -2206,6 +2287,7 @@ mDNSlocal mStatus UpdateInterfaceList(mDNS *const m, mDNSs32 utc) else { int ifru_flags6 = 0; +#ifndef NO_IPV6 if (ifa->ifa_addr->sa_family == AF_INET6 && InfoSocket >= 0) { struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; @@ -2217,6 +2299,7 @@ mDNSlocal mStatus UpdateInterfaceList(mDNS *const m, mDNSs32 utc) ifru_flags6 = ifr6.ifr_ifru.ifru_flags6; verbosedebugf("%s %.16a %04X %04X", ifa->ifa_name, &sin6->sin6_addr, ifa->ifa_flags, ifru_flags6); } +#endif if (!(ifru_flags6 & (IN6_IFF_NOTREADY | IN6_IFF_DETACHED | IN6_IFF_DEPRECATED | IN6_IFF_TEMPORARY))) { if (ifa->ifa_flags & IFF_LOOPBACK) @@ -2225,7 +2308,7 @@ mDNSlocal mStatus UpdateInterfaceList(mDNS *const m, mDNSs32 utc) else { NetworkInterfaceInfoOSX *i = AddInterfaceToList(m, ifa, utc); - if (i && i->Multicast) + if (i && MulticastInterface(i)) { if (ifa->ifa_addr->sa_family == AF_INET) foundav4 = mDNStrue; else foundav6 = mDNStrue; @@ -2253,14 +2336,17 @@ mDNSlocal mStatus UpdateInterfaceList(mDNS *const m, mDNSs32 utc) for (i = m->p->InterfaceList; i; i = i->next) if (i->Exists) { - mDNSBool txrx = i->Multicast && ((i->ifinfo.ip.type == mDNSAddrType_IPv4) || !FindRoutableIPv4(m, i->scope_id)); + mDNSBool txrx = MulticastInterface(i) && ((i->ifinfo.ip.type == mDNSAddrType_IPv4) || !FindRoutableIPv4(m, i->scope_id)); if (i->ifinfo.McastTxRx != txrx) { i->ifinfo.McastTxRx = txrx; i->Exists = 2; // State change; need to deregister and reregister this interface } } + +#ifndef NO_IPV6 if (InfoSocket >= 0) close(InfoSocket); +#endif mDNS_snprintf(defaultname, sizeof(defaultname), "Macintosh-%02X%02X%02X%02X%02X%02X", PrimaryMAC.b[0], PrimaryMAC.b[1], PrimaryMAC.b[2], PrimaryMAC.b[3], PrimaryMAC.b[4], PrimaryMAC.b[5]); @@ -2346,12 +2432,14 @@ mDNSlocal int SetupActiveInterfaces(mDNS *const m, mDNSs32 utc) // If i->LastSeen == utc, then this is a brand-new interface, just created, or an interface that never went away. // If i->LastSeen != utc, then this is an old interface, previously seen, that went away for (utc - i->LastSeen) seconds. // If the interface is an old one that went away and came back in less than a minute, then we're in a flapping scenario. - mDNSBool flapping = (utc - i->LastSeen > 0 && utc - i->LastSeen < 60); - mDNS_RegisterInterface(m, n, flapping ? mDNSPlatformOneSecond * 5 : 0); + i->Occulting = !(i->ifa_flags & IFF_LOOPBACK) && (utc - i->LastSeen > 0 && utc - i->LastSeen < 60); + mDNS_RegisterInterface(m, n, i->Flashing && i->Occulting); if (i->ifinfo.ip.type == mDNSAddrType_IPv4 && (i->ifinfo.ip.ip.v4.b[0] != 169 || i->ifinfo.ip.ip.v4.b[1] != 254)) count++; - LogOperation("SetupActiveInterfaces: Registered %5s(%lu) %.6a InterfaceID %p %#a/%d%s%s", + LogOperation("SetupActiveInterfaces: Registered %5s(%lu) %.6a InterfaceID %p %#a/%d%s%s%s", i->ifa_name, i->scope_id, &i->BSSID, primary, &n->ip, CountMaskBits(&n->mask), - flapping ? " (Flapping)" : "", n->InterfaceActive ? " (Primary)" : ""); + i->Flashing ? " (Flashing)" : "", + i->Occulting ? " (Occulting)" : "", + n->InterfaceActive ? " (Primary)" : ""); } if (!n->McastTxRx) @@ -2365,12 +2453,14 @@ mDNSlocal int SetupActiveInterfaces(mDNS *const m, mDNSs32 utc) else LogMsg("SetupActiveInterfaces: v4 socket%2d %5s(%lu) %.6a InterfaceID %p %#a/%d FAILED", primary->ss.sktv4, i->ifa_name, i->scope_id, &i->BSSID, n->InterfaceID, &n->ip, CountMaskBits(&n->mask)); } +#ifndef NO_IPV6 if (i->sa_family == AF_INET6 && primary->ss.sktv6 == -1) { mStatus err = SetupSocket(m, &primary->ss, mDNStrue, &i->ifinfo.ip, AF_INET6); if (err == 0) debugf("SetupActiveInterfaces: v6 socket%2d %5s(%lu) %.6a InterfaceID %p %#a/%d", primary->ss.sktv6, i->ifa_name, i->scope_id, &i->BSSID, n->InterfaceID, &n->ip, CountMaskBits(&n->mask)); else LogMsg("SetupActiveInterfaces: v6 socket%2d %5s(%lu) %.6a InterfaceID %p %#a/%d FAILED", primary->ss.sktv6, i->ifa_name, i->scope_id, &i->BSSID, n->InterfaceID, &n->ip, CountMaskBits(&n->mask)); } +#endif } } return count; @@ -2427,10 +2517,14 @@ mDNSlocal int ClearInactiveInterfaces(mDNS *const m, mDNSs32 utc) if (i->ifinfo.InterfaceID) if (i->Exists == 0 || i->Exists == 2 || i->ifinfo.InterfaceID != (mDNSInterfaceID)primary) { - LogOperation("ClearInactiveInterfaces: Deregistering %5s(%lu) %.6a InterfaceID %p %#a/%d%s", + i->Flashing = !(i->ifa_flags & IFF_LOOPBACK) && (utc - i->AppearanceTime < 60); + LogOperation("ClearInactiveInterfaces: Deregistering %5s(%lu) %.6a InterfaceID %p %#a/%d%s%s%s", i->ifa_name, i->scope_id, &i->BSSID, i->ifinfo.InterfaceID, - &i->ifinfo.ip, CountMaskBits(&i->ifinfo.mask), i->ifinfo.InterfaceActive ? " (Primary)" : ""); - mDNS_DeregisterInterface(m, &i->ifinfo); + &i->ifinfo.ip, CountMaskBits(&i->ifinfo.mask), + i->Flashing ? " (Flashing)" : "", + i->Occulting ? " (Occulting)" : "", + i->ifinfo.InterfaceActive ? " (Primary)" : ""); + mDNS_DeregisterInterface(m, &i->ifinfo, i->Flashing && i->Occulting); if (i->ifinfo.ip.type == mDNSAddrType_IPv4 && (i->ifinfo.ip.ip.v4.b[0] != 169 || i->ifinfo.ip.ip.v4.b[1] != 254)) count++; i->ifinfo.InterfaceID = mDNSNULL; // NOTE: If n->InterfaceID is set, that means we've called mDNS_RegisterInterface() for this interface, @@ -2702,7 +2796,7 @@ mDNSlocal void MarkSearchListElem(const char *d) if (!MakeDomainNameFromDNSNameString(&domain, d)) { LogMsg("ERROR: MarkSearchListElem - bad domain %##s", d); return; } - if (SameDomainName(&domain, &localdomain) || SameDomainName(&domain, &LocalReverseMapomain)) + if (SameDomainName(&domain, &localdomain) || SameDomainName(&domain, &LocalReverseMapDomain)) { debugf("MarkSearchListElem - ignoring local domain %##s", domain.c); return; } // if domain is in list, mark as pre-existent (0) @@ -2896,9 +2990,10 @@ mDNSlocal void SCPrefsDynDNSCallback(mDNS *const m, AuthRecord *const rr, mStatu mDNSlocal void SetSecretForDomain(mDNS *m, const domainname *domain) { +#ifndef NO_SECURITYFRAMEWORK OSStatus err = 0; char dstring[MAX_ESCAPED_DOMAIN_NAME]; - mDNSu32 secretlen; + UInt32 secretlen; void *secret = NULL; domainname *d, canon; int i, dlen; @@ -2935,7 +3030,7 @@ mDNSlocal void SetSecretForDomain(mDNS *m, const domainname *domain) err = SecKeychainSearchCopyNext(searchRef, &itemRef); if (!err) { - mDNSu32 tags[1]; + UInt32 tags[1]; SecKeychainAttributeInfo attrInfo; mDNSu32 i; char keybuf[MAX_ESCAPED_DOMAIN_NAME+1]; @@ -2975,6 +3070,10 @@ mDNSlocal void SetSecretForDomain(mDNS *m, const domainname *domain) if (err && err != errSecItemNotFound) LogMsg("Error: SetSecretForDomain - %s failed with error code %d", failedfn, err); if (attrList) SecKeychainItemFreeAttributesAndData(attrList, secret); if (itemRef) CFRelease(itemRef); +#else + (void)m; (void)domain; + LogMsg("Error: SetSecretForDomain - no keychain support"); +#endif /* NO_SECURITYFRAMEWORK */ } mDNSlocal void SetSCPrefsBrowseDomainsFromCFArray(mDNS *m, CFArrayRef browseDomains, mDNSBool add) @@ -3282,6 +3381,7 @@ exit: return(err); } +#ifndef NO_IOPOWER mDNSlocal void PowerChanged(void *refcon, io_service_t service, natural_t messageType, void *messageArgument) { mDNS *const m = (mDNS *const)refcon; @@ -3324,6 +3424,7 @@ mDNSlocal mStatus WatchForPowerChanges(mDNS *const m) } return(-1); } +#endif /* NO_IOPOWER */ CF_EXPORT CFDictionaryRef _CFCopySystemVersionDictionary(void); CF_EXPORT const CFStringRef _kCFSystemVersionProductNameKey; @@ -3336,7 +3437,7 @@ CF_EXPORT const CFStringRef _kCFSystemVersionBuildVersionKey; mDNSexport int mDNSMacOSXSystemBuildNumber(char *HINFO_SWstring) { int major = 0, minor = 0; - char letter = 0, prodname[256]="Mac OS X", prodvers[256]="", buildver[256]="?"; + char letter = 0, prodname[256]="", prodvers[256]="", buildver[256]=""; CFDictionaryRef vers = _CFCopySystemVersionDictionary(); if (vers) { @@ -3349,6 +3450,7 @@ mDNSexport int mDNSMacOSXSystemBuildNumber(char *HINFO_SWstring) sscanf(buildver, "%d%c%d", &major, &letter, &minor); CFRelease(vers); } + if (!major) { major=8; LogMsg("Note: No Major Build Version number found; assuming 8"); } if (HINFO_SWstring) mDNS_snprintf(HINFO_SWstring, 256, "%s %s (%s), %s", prodname, prodvers, buildver, mDNSResponderVersionString); return(major); } @@ -3540,6 +3642,7 @@ mDNSlocal mStatus mDNSPlatformInit_setup(mDNS *const m) if (mDNSMacOSXSystemBuildNumber(HINFO_SWstring) < 7) m->KnownBugs |= mDNS_KnownBug_PhantomInterfaces; if (mDNSPlatformInit_CanReceiveUnicast()) m->CanReceiveUnicastOn5353 = mDNStrue; +#ifndef NO_HINFO mDNSu32 hlen = mDNSPlatformStrLen(HINFO_HWstring); mDNSu32 slen = mDNSPlatformStrLen(HINFO_SWstring); if (hlen + slen < 254) @@ -3549,6 +3652,7 @@ mDNSlocal mStatus mDNSPlatformInit_setup(mDNS *const m) mDNSPlatformMemCopy(HINFO_HWstring, &m->HIHardware.c[1], hlen); mDNSPlatformMemCopy(HINFO_SWstring, &m->HISoftware.c[1], slen); } +#endif /* NO_HINFO */ m->p->unicastsockets.m = m; m->p->unicastsockets.info = NULL; @@ -3557,16 +3661,20 @@ mDNSlocal mStatus mDNSPlatformInit_setup(mDNS *const m) m->p->unicastsockets.rlsv4 = m->p->unicastsockets.rlsv6 = NULL; err = SetupSocket(m, &m->p->unicastsockets, mDNSfalse, &zeroAddr, AF_INET); +#ifndef NO_IPV6 err = SetupSocket(m, &m->p->unicastsockets, mDNSfalse, &zeroAddr, AF_INET6); +#endif struct sockaddr_in s4; - struct sockaddr_in6 s6; socklen_t n4 = sizeof(s4); - socklen_t n6 = sizeof(s6); if (getsockname(m->p->unicastsockets.sktv4, (struct sockaddr *)&s4, &n4) < 0) LogMsg("getsockname v4 error %d (%s)", errno, strerror(errno)); else m->UnicastPort4.NotAnInteger = s4.sin_port; +#ifndef NO_IPV6 + struct sockaddr_in6 s6; + socklen_t n6 = sizeof(s6); if (getsockname(m->p->unicastsockets.sktv6, (struct sockaddr *)&s6, &n6) < 0) LogMsg("getsockname v6 error %d (%s)", errno, strerror(errno)); else m->UnicastPort6.NotAnInteger = s6.sin6_port; +#endif m->p->InterfaceList = mDNSNULL; m->p->userhostlabel.c[0] = 0; @@ -3579,8 +3687,10 @@ mDNSlocal mStatus mDNSPlatformInit_setup(mDNS *const m) err = WatchForNetworkChanges(m); if (err) return(err); +#ifndef NO_IOPOWER err = WatchForPowerChanges(m); if (err) return err; +#endif /* NO_IOPOWER */ DynDNSRegDomain.c[0] = '\0'; DynDNSConfigChanged(m); // Get initial DNS configuration @@ -3606,7 +3716,9 @@ mDNSexport void mDNSPlatformClose(mDNS *const m) CFRunLoopRemoveSource(CFRunLoopGetCurrent(), m->p->PowerRLS, kCFRunLoopDefaultMode); CFRunLoopSourceInvalidate(m->p->PowerRLS); CFRelease(m->p->PowerRLS); +#ifndef NO_IOPOWER IODeregisterForSystemPower(&m->p->PowerNotifier); +#endif /* NO_IOPOWER */ m->p->PowerConnection = 0; m->p->PowerNotifier = 0; m->p->PowerRLS = NULL; diff --git a/mDNSMacOSX/mDNSMacOSX.h b/mDNSMacOSX/mDNSMacOSX.h index 638f095..3e14608 100644 --- a/mDNSMacOSX/mDNSMacOSX.h +++ b/mDNSMacOSX/mDNSMacOSX.h @@ -1,28 +1,34 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: mDNSMacOSX.h,v $ +Revision 1.55.2.1 2006/08/29 06:48:07 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + +Revision 1.55 2006/06/29 05:33:30 cheshire + mDNSResponder conditional compilation options + +Revision 1.54 2006/03/19 03:27:49 cheshire + Suppress "interface flapping" logic for loopback + +Revision 1.53 2006/03/19 02:00:09 cheshire + Improve logic for delaying packets after repeated interface transitions + Revision 1.52 2006/01/05 21:41:49 cheshire Reword "mach_absolute_time went backwards" dialog @@ -237,12 +243,18 @@ struct NetworkInterfaceInfoOSX_struct NetworkInterfaceInfoOSX *next; mDNSu32 Exists; // 1 = currently exists in getifaddrs list; 0 = doesn't // 2 = exists, but McastTxRx state changed + mDNSs32 AppearanceTime; // Time this interface appeared most recently in getifaddrs list + // i.e. the first time an interface is seen, AppearanceTime is set. + // If an interface goes away temporarily and then comes back then + // AppearanceTime is updated to the time of the most recent appearance. mDNSs32 LastSeen; // If Exists==0, last time this interface appeared in getifaddrs list + mDNSBool Flashing; // Set if interface appeared for less than 60 seconds and then vanished + mDNSBool Occulting; // Set if interface vanished for less than 60 seconds and then came back char *ifa_name; // Memory for this is allocated using malloc mDNSu32 scope_id; // interface index / IPv6 scope ID mDNSEthAddr BSSID; // BSSID of 802.11 base station, if applicable u_short sa_family; - mDNSBool Multicast; + unsigned int ifa_flags; CFSocketSet ss; }; diff --git a/mDNSMacOSX/mDNSMacOSXPuma.c b/mDNSMacOSX/mDNSMacOSXPuma.c index 7764e2a..cf2d86f 100644 --- a/mDNSMacOSX/mDNSMacOSXPuma.c +++ b/mDNSMacOSX/mDNSMacOSXPuma.c @@ -1,24 +1,18 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ * * This file is not normally used. * It can be conditionally compiled in by defining RUN_ON_PUMA_WITHOUT_IFADDRS @@ -31,6 +25,9 @@ Change History (most recent first): $Log: mDNSMacOSXPuma.c,v $ +Revision 1.6 2006/08/14 23:24:40 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.5 2004/09/20 23:52:02 cheshire CFSocket{Puma}.c renamed to mDNSMacOSX{Puma}.c diff --git a/mDNSMacOSX/mDNSResponder.pbproj/project.pbxproj b/mDNSMacOSX/mDNSResponder.pbproj/project.pbxproj index 6c92377..b6d7438 100644 --- a/mDNSMacOSX/mDNSResponder.pbproj/project.pbxproj +++ b/mDNSMacOSX/mDNSResponder.pbproj/project.pbxproj @@ -22,8 +22,8 @@ buildSettings = { FRAMEWORK_SEARCH_PATHS = ""; GCC_TREAT_WARNINGS_AS_ERRORS = YES; - HEADER_SEARCH_PATHS = "../mDNSShared \"${APPLE_INTERNAL_DEVELOPER_DIR}/Headers\" \"${OBJROOT}/mDNSResponder.build\""; - LIBRARY_SEARCH_PATHS = "\"${OBJROOT}/mDNSResponder.build\""; + HEADER_SEARCH_PATHS = "../mDNSShared \"${APPLE_INTERNAL_DEVELOPER_DIR}/Headers\" \"${CONFIGURATION_TEMP_DIR}\""; + LIBRARY_SEARCH_PATHS = "\"${CONFIGURATION_TEMP_DIR}\""; MACOSX_DEPLOYMENT_TARGET = 10.2; OPTIMIZATION_CFLAGS = "-O0"; OTHER_CFLAGS = "-no-cpp-precomp -mdynamic-no-pic -D__MACOSX__ -DmDNSResponderVersion=${MVERS} -D_LEGACY_NAT_TRAVERSAL_ -DMDNS_DEBUGMSGS=1"; @@ -200,6 +200,8 @@ ); buildSettings = { MVERS = "\"mDNSResponder (Engineering Build)\""; + CONFIGURATION_BUILD_DIR = "${BUILD_DIR}"; + CONFIGURATION_TEMP_DIR = "${BUILD_DIR}/mDNSResponder.build"; }; isa = PBXBuildStyle; name = Development; @@ -329,9 +331,9 @@ buildSettings = { FRAMEWORK_SEARCH_PATHS = ""; GCC_TREAT_WARNINGS_AS_ERRORS = YES; - HEADER_SEARCH_PATHS = "../mDNSShared \"${APPLE_INTERNAL_DEVELOPER_DIR}/Headers\" \"${OBJROOT}/mDNSResponder.build\""; + HEADER_SEARCH_PATHS = "../mDNSShared \"${APPLE_INTERNAL_DEVELOPER_DIR}/Headers\" \"${CONFIGURATION_TEMP_DIR}\""; INSTALL_PATH = /usr/sbin; - LIBRARY_SEARCH_PATHS = "\"${OBJROOT}/mDNSResponder.build\""; + LIBRARY_SEARCH_PATHS = "\"${CONFIGURATION_TEMP_DIR}\""; MACOSX_DEPLOYMENT_TARGET = 10.2; OTHER_CFLAGS = "-no-cpp-precomp -mdynamic-no-pic -D__MACOSX__ -DmDNSResponderVersion=${MVERS} -D_LEGACY_NAT_TRAVERSAL_"; OTHER_LDFLAGS = "-ldnsinfo"; @@ -809,6 +811,8 @@ DB2CC44D0662DD1100335AB3, DB2CC44E0662DD1100335AB3, DB2CC44F0662DD1100335AB3, + FF2C5FB00A48B8680066DA11, + FF2C5FB20A48B86E0066DA11, ); isa = PBXGroup; name = "Java Support"; @@ -920,6 +924,8 @@ DB2CC45F0662DE4C00335AB3, DB2CC4600662DE4C00335AB3, DB2CC4610662DE4D00335AB3, + FF2C5FB10A48B8680066DA11, + FF2C5FB30A48B86E0066DA11, ); isa = PBXSourcesBuildPhase; runOnlyForDeploymentPostprocessing = 0; @@ -954,7 +960,8 @@ JAVA_ARCHIVE_COMPRESSION = YES; JAVA_ARCHIVE_TYPE = JAR; JAVA_COMPILER_DEBUGGING_SYMBOLS = NO; - JAVA_COMPILER_TARGET_VM_VERSION = 1.2; + JAVA_COMPILER_SOURCE_VERSION = 1.4; + JAVA_COMPILER_TARGET_VM_VERSION = 1.4; JAVA_SOURCE_SUBDIR = .; LIBRARY_STYLE = STATIC; MACOSX_DEPLOYMENT_TARGET = 10.2; @@ -966,6 +973,7 @@ PURE_JAVA = YES; REZ_EXECUTABLE = YES; SECTORDER_FLAGS = ""; + STRIPFLAGS = "-S"; WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas"; }; comments = "Multiplatform .jar file that implements Java interface to DNS-SD"; @@ -988,7 +996,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "if [ -d ${OBJROOT}/mDNSResponder.build/${CONFIGURATION} ]; then BUILD_DIR=${OBJROOT}/mDNSResponder.build/${CONFIGURATION}; else BUILD_DIR=${OBJROOT}/mDNSResponder.build; fi\njavah -force -classpath ${BUILD_DIR}/dns_sd.jar.build/JavaClasses/ -o ${BUILD_DIR}/dns_sd.jar.build/DNSSD.java.h com.apple.dnssd.AppleDNSSD com.apple.dnssd.AppleBrowser com.apple.dnssd.AppleResolver com.apple.dnssd.AppleRegistration com.apple.dnssd.AppleQuery com.apple.dnssd.AppleDomainEnum com.apple.dnssd.AppleService"; + shellScript = "javah -force -J-Xbootclasspath/p:${CONFIGURATION_TEMP_DIR}/dns_sd.jar.build/JavaClasses -o ${CONFIGURATION_TEMP_DIR}/dns_sd.jar.build/DNSSD.java.h com.apple.dnssd.AppleDNSSD com.apple.dnssd.AppleBrowser com.apple.dnssd.AppleResolver com.apple.dnssd.AppleRegistration com.apple.dnssd.AppleQuery com.apple.dnssd.AppleDomainEnum com.apple.dnssd.AppleService"; }; DB2CC4560662DE4500335AB3 = { fileRef = DB2CC4430662DD1100335AB3; @@ -1100,10 +1108,9 @@ DB2CC4650662DF5C00335AB3, ); buildSettings = { - DEBUGGING_SYMBOLS = NO; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; - HEADER_SEARCH_PATHS = "../mDNSShared \"${SYSTEM_LIBRARY_DIR}/Frameworks/JavaVM.framework/Versions/A/Headers\" \"${SYSTEM_LIBRARY_DIR}/Frameworks/JavaVM.framework/Versions/1.3.1/Headers\" \"${OBJROOT}/mDNSResponder.build/dns_sd.jar.build\" \"${OBJROOT}/mDNSResponder.build/${CONFIGURATION}/dns_sd.jar.build\""; + HEADER_SEARCH_PATHS = "../mDNSShared \"${SYSTEM_LIBRARY_DIR}/Frameworks/JavaVM.framework/Versions/A/Headers\" \"${SYSTEM_LIBRARY_DIR}/Frameworks/JavaVM.framework/Versions/1.3.1/Headers\" \"${CONFIGURATION_TEMP_DIR}/dns_sd.jar.build\""; INSTALL_PATH = /usr/lib/java; LIBRARY_STYLE = DYNAMIC; MACOSX_DEPLOYMENT_TARGET = 10.2; @@ -1113,6 +1120,7 @@ PRODUCT_NAME = libjdns_sd.jnilib; REZ_EXECUTABLE = YES; SECTORDER_FLAGS = ""; + STRIPFLAGS = "-S"; WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas"; }; comments = "Platform-specific JNI library that bridges dns_sd.jar to ."; @@ -1676,6 +1684,7 @@ PREBINDING = NO; PRODUCT_NAME = Bonjour; SECTORDER_FLAGS = ""; + STRIPFLAGS = "-S"; WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas"; WRAPPER_EXTENSION = prefPane; }; @@ -1981,6 +1990,32 @@ isa = PBXTargetDependency; target = FF2609E107B440DD00CE10E5; }; + FF2C5FB00A48B8680066DA11 = { + fileEncoding = 4; + isa = PBXFileReference; + name = DNSSDRecordRegistrar.java; + path = ../mDNSShared/Java/DNSSDRecordRegistrar.java; + refType = 2; + }; + FF2C5FB10A48B8680066DA11 = { + fileRef = FF2C5FB00A48B8680066DA11; + isa = PBXBuildFile; + settings = { + }; + }; + FF2C5FB20A48B86E0066DA11 = { + fileEncoding = 4; + isa = PBXFileReference; + name = RegisterRecordListener.java; + path = ../mDNSShared/Java/RegisterRecordListener.java; + refType = 2; + }; + FF2C5FB30A48B86E0066DA11 = { + fileRef = FF2C5FB20A48B86E0066DA11; + isa = PBXBuildFile; + settings = { + }; + }; FF354EB108516C63007C00E1 = { fileEncoding = 4; isa = PBXExecutableFileReference; @@ -2005,7 +2040,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "if [ -e /usr/local/include/dnsinfo.h ]\nthen\nrm -f \"${OBJROOT}/mDNSResponder.build/dnsinfo.h\"\nrm -f \"${OBJROOT}/mDNSResponder.build/libdnsinfo.a\"\nelse\necho \"#define MDNS_NO_DNSINFO 1\" > ${OBJROOT}/mDNSResponder.build/dnsinfo.h\ntouch ${OBJROOT}/mDNSResponder.build/empty.c\ncc ${OBJROOT}/mDNSResponder.build/empty.c -c -o \"${OBJROOT}/mDNSResponder.build/libdnsinfo.a\"\nrm -f ${OBJROOT}/mDNSResponder.build/empty.c\nfi"; + shellScript = "if [ -e /usr/local/include/dnsinfo.h ]\nthen\nrm -f \"${CONFIGURATION_TEMP_DIR}/dnsinfo.h\"\nrm -f \"${CONFIGURATION_TEMP_DIR}/libdnsinfo.a\"\nelse\necho \"#define MDNS_NO_DNSINFO 1\" > ${CONFIGURATION_TEMP_DIR}/dnsinfo.h\ntouch ${CONFIGURATION_TEMP_DIR}/empty.c\ncc ${CONFIGURATION_TEMP_DIR}/empty.c -c -o \"${CONFIGURATION_TEMP_DIR}/libdnsinfo.a\"\nrm -f ${CONFIGURATION_TEMP_DIR}/empty.c\nfi"; }; FF485D5105632E0000130380 = { fileEncoding = 4; @@ -2087,7 +2122,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "rm -f ${BUILD_DIR}/${CONFIGURATION}/dns_sd"; + shellScript = "rm -f ${CONFIGURATION_BUILD_DIR}/dns_sd"; }; FFD41DDF06641BBB00F0C438 = { isa = PBXTargetDependency; @@ -2154,7 +2189,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "if [ -e /usr/local/include/dnsinfo.h ]\nthen\nrm -f \"${OBJROOT}/mDNSResponder.build/dnsinfo.h\"\nrm -f \"${OBJROOT}/mDNSResponder.build/libdnsinfo.a\"\nelse\necho \"#define MDNS_NO_DNSINFO 1\" > ${OBJROOT}/mDNSResponder.build/dnsinfo.h\ntouch ${OBJROOT}/mDNSResponder.build/empty.c\ncc ${OBJROOT}/mDNSResponder.build/empty.c -c -o \"${OBJROOT}/mDNSResponder.build/libdnsinfo.a\"\nrm -f ${OBJROOT}/mDNSResponder.build/empty.c\nfi"; + shellScript = "if [ -e /usr/local/include/dnsinfo.h ]\nthen\nrm -f \"${CONFIGURATION_TEMP_DIR}/dnsinfo.h\"\nrm -f \"${CONFIGURATION_TEMP_DIR}/libdnsinfo.a\"\nelse\necho \"#define MDNS_NO_DNSINFO 1\" > ${CONFIGURATION_TEMP_DIR}/dnsinfo.h\ntouch ${CONFIGURATION_TEMP_DIR}/empty.c\ncc ${CONFIGURATION_TEMP_DIR}/empty.c -c -o \"${CONFIGURATION_TEMP_DIR}/libdnsinfo.a\"\nrm -f ${CONFIGURATION_TEMP_DIR}/empty.c\nfi"; }; FFFB0DA407B43BED00B88D48 = { children = ( @@ -2212,6 +2247,7 @@ FFFB0DA807B43C9100B88D48, ); buildSettings = { + INSTALL_PATH = "/Library/Application Support/Bonjour"; MACOSX_DEPLOYMENT_TARGET = 10.2; OTHER_CFLAGS = ""; OTHER_LDFLAGS = ""; @@ -2219,13 +2255,14 @@ PRODUCT_NAME = ddnswriteconfig; REZ_EXECUTABLE = YES; SECTORDER_FLAGS = ""; + STRIPFLAGS = "-S"; WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas"; }; dependencies = ( ); isa = PBXToolTarget; name = ddnswriteconfig; - productInstallPath = /usr/local/bin; + productInstallPath = "/Library/Application Support/Bonjour"; productName = ddnswriteconfig; productReference = FFFB0DAA07B43C9100B88D48; }; diff --git a/mDNSPosix/Client.c b/mDNSPosix/Client.c index 6aafe37..9c23772 100755 --- a/mDNSPosix/Client.c +++ b/mDNSPosix/Client.c @@ -2,28 +2,27 @@ * * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: Client.c,v $ +Revision 1.18 2006/08/14 23:24:46 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + +Revision 1.17 2006/06/12 18:22:42 cheshire + mDNSResponder building warnings under Red Hat 64-bit (LP64) Linux + Revision 1.16 2005/02/04 01:00:53 cheshire Add '-d' command-line option to specify domain to browse @@ -281,7 +280,7 @@ int main(int argc, char **argv) result = 2; } if ( (result != 0) || (gMDNSPlatformPosixVerboseLevel > 0) ) { - fprintf(stderr, "%s: Finished with status %ld, result %d\n", gProgramName, status, result); + fprintf(stderr, "%s: Finished with status %d, result %d\n", gProgramName, (int)status, result); } return 0; diff --git a/mDNSPosix/ExampleClientApp.c b/mDNSPosix/ExampleClientApp.c index 17843af..15bb86a 100644 --- a/mDNSPosix/ExampleClientApp.c +++ b/mDNSPosix/ExampleClientApp.c @@ -2,28 +2,27 @@ * * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: ExampleClientApp.c,v $ +Revision 1.14 2006/08/14 23:24:46 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + +Revision 1.13 2006/02/23 23:38:43 cheshire + On FreeBSD 4 "arpa/inet.h" requires "netinet/in.h" be included first + Revision 1.12 2004/11/30 22:37:00 cheshire Update copyright dates and add "Mode: C; tab-width: 4" headers @@ -55,8 +54,8 @@ Add log header #include // For strlen() etc. #include // For select() #include // For errno, EINTR -#include // For inet_addr() #include // For INADDR_NONE +#include // For inet_addr() #include // For gethostbyname() #include // For SIGINT, etc. diff --git a/mDNSPosix/ExampleClientApp.h b/mDNSPosix/ExampleClientApp.h index fa9f0fc..3438260 100644 --- a/mDNSPosix/ExampleClientApp.h +++ b/mDNSPosix/ExampleClientApp.h @@ -2,28 +2,24 @@ * * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: ExampleClientApp.h,v $ +Revision 1.7 2006/08/14 23:24:46 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.6 2004/11/30 22:37:00 cheshire Update copyright dates and add "Mode: C; tab-width: 4" headers diff --git a/mDNSPosix/Identify.c b/mDNSPosix/Identify.c index c1724f2..a9aa3b1 100644 --- a/mDNSPosix/Identify.c +++ b/mDNSPosix/Identify.c @@ -2,24 +2,17 @@ * * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ * * Formatting notes: * This code follows the "Whitesmiths style" C indentation rules. Plenty of discussion @@ -37,6 +30,12 @@ Change History (most recent first): $Log: Identify.c,v $ +Revision 1.36 2006/08/14 23:24:46 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + +Revision 1.35 2006/06/12 18:22:42 cheshire + mDNSResponder building warnings under Red Hat 64-bit (LP64) Linux + Revision 1.34 2004/12/16 20:17:11 cheshire Cache memory management improvements @@ -400,7 +399,7 @@ mDNSexport int main(int argc, char **argv) gRRCache, RR_CACHE_SIZE, mDNS_Init_DontAdvertiseLocalAddresses, mDNS_Init_NoInitCallback, mDNS_Init_NoInitCallbackContext); - if (status) { fprintf(stderr, "Daemon start: mDNS_Init failed %ld\n", status); return(status); } + if (status) { fprintf(stderr, "Daemon start: mDNS_Init failed %d\n", (int)status); return(status); } signal(SIGINT, HandleSIG); // SIGINT is what you get for a Ctrl-C signal(SIGTERM, HandleSIG); diff --git a/mDNSPosix/Makefile b/mDNSPosix/Makefile index 7176e0e..57824f4 100755 --- a/mDNSPosix/Makefile +++ b/mDNSPosix/Makefile @@ -23,7 +23,27 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # +# IMPORTANT NOTE: This is a Makefile for *GNU make* +# On some systems, a different program may be the default "make" command. +# If "make os=xxx" gives lots of errors like "Missing dependency operator", +# then try typing "gmake os=xxx" instead. +# # $Log: Makefile,v $ +# Revision 1.71 2006/06/20 23:07:04 rpantos +# Java needs to implement DNSServiceRegisterRecord equivalent +# +# Revision 1.70 2006/05/03 23:35:10 cheshire +# Add missing dependency: NetMonitor.c textually imports mDNS.c +# +# Revision 1.69 2006/02/26 23:18:50 cheshire +# FreeBSD 4 requires "-pthread" option to compile threaded code +# +# Revision 1.68 2006/02/26 01:36:54 cheshire +# Rename the poorly named "LIBFLAGS" as "LINKOPTS" +# +# Revision 1.67 2006/02/25 23:14:29 cheshire +# Add comment suggesting using "gmake" command +# # Revision 1.66 2006/01/06 01:06:17 cheshire # Compile library and client programs in one pass # @@ -253,7 +273,9 @@ CP = cp RM = rm LN = ln -s -f CFLAGS_COMMON = -I. -I$(COREDIR) -I$(SHAREDDIR) -W -Wall -DPID_FILE=\"/var/run/mdnsd.pid\" -DMDNS_UDS_SERVERPATH=\"/var/run/mdnsd\" -LIBFLAGS = +CFLAGS_PTHREAD = +LINKOPTS = +LINKOPTS_PTHREAD = -lpthread LDSUFFIX = so JAVACFLAGS_OS = -fPIC -shared -ldns_sd @@ -280,7 +302,7 @@ CFLAGS_OS = -DNOT_HAVE_DAEMON -DNOT_HAVE_SA_LEN -DNOT_HAVE_SOCKLEN_T -DNOT_HAVE_ -DLOG_PERROR=0 -D_XPG4_2 -D__EXTENSIONS__ -DHAVE_BROKEN_RECVIF_NAME CC = gcc LD = gcc -shared -LIBFLAGS = -lsocket -lnsl -lresolv +LINKOPTS = -lsocket -lnsl -lresolv JAVACFLAGS_OS += -I$(JDK)/include/solaris ifneq ($(DEBUG),1) STRIP = strip @@ -306,6 +328,14 @@ LOCALBASE?=/usr/local INSTBASE=$(LOCALBASE) STARTUPSCRIPTNAME=mdns.sh CFLAGS_OS = +# FreeBSD 4 requires threaded code to be compiled and linked using the "-pthread" option, +# and requires that the "-lpthread" link option NOT be used +# This appies only to FreeBSD -- "man cc" on FreeBSD says: +# FreeBSD SPECIFIC OPTIONS +# -pthread +# Link a user-threaded process against libc_r instead of libc. +CFLAGS_PTHREAD = -pthread -D_THREAD_SAFE +LINKOPTS_PTHREAD = -pthread JAVACFLAGS_OS += -I$(JDK)/include/freebsd LDCONFIG = ldconfig else @@ -318,7 +348,7 @@ else ifeq ($(os),jaguar) CFLAGS_OS = -DHAVE_IPV6 -no-cpp-precomp -Werror -DNOT_HAVE_SOCKLEN_T LD = libtool -dynamic -LIBFLAGS = -lSystem +LINKOPTS = -lSystem LDSUFFIX = dylib JDK = /System/Library/Frameworks/JavaVM.framework/Home JAVACFLAGS_OS = -dynamiclib -I/System/Library/Frameworks/JavaVM.framework/Headers -framework JavaVM @@ -327,7 +357,7 @@ else ifeq ($(os),panther) CFLAGS_OS = -DHAVE_IPV6 -no-cpp-precomp -Werror LD = libtool -dynamic -LIBFLAGS = -lSystem +LINKOPTS = -lSystem LDSUFFIX = dylib JDK = /System/Library/Frameworks/JavaVM.framework/Home JAVACFLAGS_OS = -dynamiclib -I/System/Library/Frameworks/JavaVM.framework/Headers -framework JavaVM @@ -337,7 +367,7 @@ ifeq ($(os),tiger) CFLAGS_OS = -DHAVE_IPV6 -no-cpp-precomp -Werror -Wdeclaration-after-statement #-Wunreachable-code CC = @gcc-4.0 LD = $(CC) -dynamiclib -LIBFLAGS = -lSystem +LINKOPTS = -lSystem LDSUFFIX = dylib JDK = /System/Library/Frameworks/JavaVM.framework/Home JAVACFLAGS_OS = -dynamiclib -I/System/Library/Frameworks/JavaVM.framework/Headers -framework JavaVM @@ -433,7 +463,7 @@ Daemon: setup $(BUILDDIR)/mdnsd @echo "Responder daemon done" $(BUILDDIR)/mdnsd: $(DAEMONOBJS) - $(CC) -o $@ $+ $(CFLAGS) $(LIBFLAGS) + $(CC) -o $@ $+ $(LINKOPTS) @$(STRIP) $@ # libdns_sd target builds the client library @@ -443,7 +473,7 @@ libdns_sd: setup $(BUILDDIR)/libdns_sd.$(LDSUFFIX) CLIENTLIBOBJS = $(OBJDIR)/dnssd_clientlib.c.so.o $(OBJDIR)/dnssd_clientstub.c.so.o $(OBJDIR)/dnssd_ipc.c.so.o $(BUILDDIR)/libdns_sd.$(LDSUFFIX): $(CLIENTLIBOBJS) - @$(LD) $(LIBFLAGS) -o $@ $+ + @$(LD) $(LINKOPTS) -o $@ $+ @$(STRIP) $@ Clients: setup libdns_sd ../Clients/build/dns-sd @@ -457,7 +487,7 @@ nss_mdns: setup $(BUILDDIR)/$(NSSLIBFILE) @echo "Name Service Switch module done" $(BUILDDIR)/$(NSSLIBFILE): $(CLIENTLIBOBJS) $(OBJDIR)/nss_mdns.c.so.o - @$(LD) $(LIBFLAGS) -o $@ $+ + @$(LD) $(LINKOPTS) -o $@ $+ @$(STRIP) $@ ############################################################################# @@ -572,6 +602,8 @@ JARCONTENTS = $(OBJDIR)/com/apple/dnssd/DNSSDService.class \ $(OBJDIR)/com/apple/dnssd/RegisterListener.class \ $(OBJDIR)/com/apple/dnssd/QueryListener.class \ $(OBJDIR)/com/apple/dnssd/DomainListener.class \ + $(OBJDIR)/com/apple/dnssd/RegisterRecordListener.class \ + $(OBJDIR)/com/apple/dnssd/DNSSDRecordRegistrar.class \ $(OBJDIR)/com/apple/dnssd/DNSSD.class $(BUILDDIR)/dns_sd.jar: $(JARCONTENTS) setup @@ -626,24 +658,26 @@ dnsextd: setup $(BUILDDIR)/dnsextd @echo "dnsextd done" $(BUILDDIR)/mDNSClientPosix: $(APPOBJ) $(OBJDIR)/Client.c.o - $(CC) $+ -o $@ $(LIBFLAGS) + $(CC) $+ -o $@ $(LINKOPTS) $(BUILDDIR)/mDNSResponderPosix: $(COMMONOBJ) $(OBJDIR)/Responder.c.o - $(CC) $+ -o $@ $(LIBFLAGS) + $(CC) $+ -o $@ $(LINKOPTS) $(BUILDDIR)/mDNSProxyResponderPosix: $(COMMONOBJ) $(OBJDIR)/ProxyResponder.c.o - $(CC) $+ -o $@ $(LIBFLAGS) + $(CC) $+ -o $@ $(LINKOPTS) $(BUILDDIR)/mDNSIdentify: $(SPECIALOBJ) $(OBJDIR)/Identify.c.o - $(CC) $+ -o $@ $(LIBFLAGS) + $(CC) $+ -o $@ $(LINKOPTS) $(OBJDIR)/Identify.c.o: $(COREDIR)/mDNS.c # Note: Identify.c textually imports mDNS.c $(BUILDDIR)/mDNSNetMonitor: $(SPECIALOBJ) $(OBJDIR)/NetMonitor.c.o - $(CC) $+ -o $@ $(LIBFLAGS) + $(CC) $+ -o $@ $(LINKOPTS) + +$(OBJDIR)/NetMonitor.c.o: $(COREDIR)/mDNS.c # Note: NetMonitor.c textually imports mDNS.c $(BUILDDIR)/dnsextd: $(SPECIALOBJ) $(OBJDIR)/dnsextd.c.threadsafe.o - $(CC) $+ -o $@ $(LIBFLAGS) -lpthread + $(CC) $+ -o $@ $(LINKOPTS) $(LINKOPTS_PTHREAD) ############################################################################# @@ -658,7 +692,7 @@ $(OBJDIR)/%.c.o: $(SHAREDDIR)/%.c $(CC) $(CFLAGS) -c -o $@ $< $(OBJDIR)/%.c.threadsafe.o: %.c - $(CC) $(CFLAGS) -D_REENTRANT -c -o $@ $< + $(CC) $(CFLAGS) $(CFLAGS_PTHREAD) -D_REENTRANT -c -o $@ $< $(OBJDIR)/%.c.so.o: %.c $(CC) $(CFLAGS) -c -fPIC -o $@ $< diff --git a/mDNSPosix/NetMonitor.c b/mDNSPosix/NetMonitor.c index 6c53cc8..da3e63e 100644 --- a/mDNSPosix/NetMonitor.c +++ b/mDNSPosix/NetMonitor.c @@ -2,24 +2,17 @@ * * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ * * Formatting notes: * This code follows the "Whitesmiths style" C indentation rules. Plenty of discussion @@ -37,6 +30,29 @@ Change History (most recent first): $Log: NetMonitor.c,v $ +Revision 1.82 2006/08/14 23:24:46 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + +Revision 1.81 2006/07/06 00:01:44 cheshire + Add Private DNS client functionality to mDNSResponder +Update mDNSSendDNSMessage() to use uDNS_TCPSocket type instead of "int" + +Revision 1.80 2006/06/12 18:22:42 cheshire + mDNSResponder building warnings under Red Hat 64-bit (LP64) Linux + +Revision 1.79 2006/04/26 20:48:33 cheshire +Make final count of unique source addresses show IPv4 and IPv6 counts separately + +Revision 1.78 2006/04/25 00:42:24 cheshire +Add ability to specify a single interface index to capture on, +e.g. typically "-i 4" for Ethernet and "-i 5" for AirPort + +Revision 1.77 2006/03/02 21:50:45 cheshire +Removed strange backslash at the end of a line + +Revision 1.76 2006/02/23 23:38:43 cheshire + On FreeBSD 4 "arpa/inet.h" requires "netinet/in.h" be included first + Revision 1.75 2006/01/05 22:33:58 cheshire Use IFNAMSIZ (more portable) instead of IF_NAMESIZE @@ -297,9 +313,9 @@ Added NetMonitor.c #include // For SIGINT, SIGTERM #include // For gethostbyname() #include // For AF_INET, AF_INET6, etc. -#include // For inet_addr() #include // For IF_NAMESIZE #include // For INADDR_NONE +#include // For inet_addr() #include "mDNSPosix.h" // Defines the specific types needed to run mDNS on this platform #include "ExampleClientApp.h" @@ -363,7 +379,7 @@ static mDNS mDNSStorage; // mDNS core uses this to store its globals static mDNS_PlatformSupport PlatformStorage; // Stores this platform's globals struct timeval tv_start, tv_end, tv_interval; - +static int FilterInterface = 0; static FilterList *Filters; #define ExactlyOneFilter (Filters && !Filters->next) @@ -557,7 +573,7 @@ mDNSlocal void SendUnicastQuery(mDNS *const m, HostEntry *entry, domainname *nam m->ExpectUnicastResponse = m->timenow; } - mDNSSendDNSMessage(&mDNSStorage, &query, qptr, InterfaceID, target, MulticastDNSPort, -1, mDNSNULL); + mDNSSendDNSMessage(&mDNSStorage, &query, qptr, InterfaceID, target, MulticastDNSPort, mDNSNULL, mDNSNULL); } mDNSlocal void AnalyseHost(mDNS *const m, HostEntry *entry, const mDNSInterfaceID InterfaceID) @@ -694,7 +710,7 @@ mDNSlocal void printstats(int max) } } -mDNSlocal const mDNSu8 *FindUpdate(mDNS *const m, const DNSMessage *const query, const mDNSu8 *ptr, const mDNSu8 *const end,\ +mDNSlocal const mDNSu8 *FindUpdate(mDNS *const m, const DNSMessage *const query, const mDNSu8 *ptr, const mDNSu8 *const end, DNSQuestion *q, LargeCacheRecord *pkt) { int i; @@ -987,6 +1003,7 @@ mDNSexport void mDNSCoreReceive(mDNS *const m, DNSMessage *const msg, const mDNS const mDNSu8 StdR = kDNSFlag0_QR_Response | kDNSFlag0_OP_StdQuery; const mDNSu8 QR_OP = (mDNSu8)(msg->h.flags.b[0] & kDNSFlag0_QROP_Mask); mDNSu8 *ptr = (mDNSu8 *)&msg->h.numQuestions; + int goodinterface = (FilterInterface == 0); (void)dstaddr; // Unused (void)dstport; // Unused @@ -999,7 +1016,8 @@ mDNSexport void mDNSCoreReceive(mDNS *const m, DNSMessage *const msg, const mDNS // For now we're only interested in monitoring IPv4 traffic. // All IPv6 packets should just be duplicates of the v4 packets. - if (AddressMatchesFilterList(srcaddr)) + if (!goodinterface) goodinterface = (FilterInterface == (int)mDNSPlatformInterfaceIndexfromInterfaceID(m, InterfaceID)); + if (goodinterface && AddressMatchesFilterList(srcaddr)) { mDNS_Lock(m); if (!mDNSAddrIsDNSMulticast(dstaddr)) @@ -1075,7 +1093,14 @@ mDNSlocal mStatus mDNSNetMonitor(void) localtime_r((time_t*)&tv_end.tv_sec, &tm); mprintf("End %3d:%02d:%02d.%06d\n", tm.tm_hour, tm.tm_min, tm.tm_sec, tv_end.tv_usec); mprintf("Captured for %3d:%02d:%02d.%06d\n", h, m, s, tv_interval.tv_usec); - if (!Filters) mprintf("Unique source addresses seen on network: %ld\n", IPv4HostList.num + IPv6HostList.num); + if (!Filters) + { + mprintf("Unique source addresses seen on network:"); + if (IPv4HostList.num) mprintf(" %ld (IPv4)", IPv4HostList.num); + if (IPv6HostList.num) mprintf(" %ld (IPv6)", IPv6HostList.num); + if (!IPv4HostList.num && !IPv6HostList.num) mprintf(" None"); + mprintf("\n"); + } mprintf("\n"); mprintf("Modern Query Packets: %7d (avg%5d/min)\n", NumPktQ, NumPktQ * mul / div); mprintf("Legacy Query Packets: %7d (avg%5d/min)\n", NumPktL, NumPktL * mul / div); @@ -1111,34 +1136,43 @@ mDNSexport int main(int argc, char **argv) for (i=1; ih_addr; - else goto usage; + struct in_addr s4; + struct in6_addr s6; + FilterList *f; + mDNSAddr a; + a.type = mDNSAddrType_IPv4; + + if (inet_pton(AF_INET, argv[i], &s4) == 1) + a.ip.v4.NotAnInteger = s4.s_addr; + else if (inet_pton(AF_INET6, argv[i], &s6) == 1) + { + a.type = mDNSAddrType_IPv6; + bcopy(&s6, &a.ip.v6, sizeof(a.ip.v6)); + } + else + { + struct hostent *h = gethostbyname(argv[i]); + if (h) a.ip.v4.NotAnInteger = *(long*)h->h_addr; + else goto usage; + } + + f = malloc(sizeof(*f)); + f->FilterAddr = a; + f->next = Filters; + Filters = f; } - - f = malloc(sizeof(*f)); - f->FilterAddr = a; - f->next = Filters; - Filters = f; } status = mDNSNetMonitor(); - if (status) { fprintf(stderr, "%s: mDNSNetMonitor failed %ld\n", progname, status); return(status); } + if (status) { fprintf(stderr, "%s: mDNSNetMonitor failed %d\n", progname, (int)status); return(status); } return(0); usage: diff --git a/mDNSPosix/PosixDaemon.c b/mDNSPosix/PosixDaemon.c index 5963f20..4bd9464 100644 --- a/mDNSPosix/PosixDaemon.c +++ b/mDNSPosix/PosixDaemon.c @@ -2,24 +2,17 @@ * * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ File: daemon.c @@ -28,6 +21,9 @@ Change History (most recent first): $Log: PosixDaemon.c,v $ +Revision 1.29.2.1 2006/08/29 06:24:34 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.29 2005/08/04 03:37:45 mkrochma Temporary workaround to fix posix after mDNS_SetPrimaryInterfaceInfo changed diff --git a/mDNSPosix/ProxyResponder.c b/mDNSPosix/ProxyResponder.c index 293ee0a..0daaca7 100644 --- a/mDNSPosix/ProxyResponder.c +++ b/mDNSPosix/ProxyResponder.c @@ -2,28 +2,30 @@ * * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: ProxyResponder.c,v $ +Revision 1.39 2006/08/14 23:24:46 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + +Revision 1.38 2006/06/12 18:22:42 cheshire + mDNSResponder building warnings under Red Hat 64-bit (LP64) Linux + +Revision 1.37 2006/02/23 23:38:43 cheshire + On FreeBSD 4 "arpa/inet.h" requires "netinet/in.h" be included first + Revision 1.36 2005/08/04 03:12:47 mkrochma Register reverse PTR record using multicast @@ -118,8 +120,8 @@ Add "$Log" header #include // For select() #include // For SIGINT, SIGTERM #include // For errno, EINTR -#include // For inet_addr() #include // For INADDR_NONE +#include // For inet_addr() #include // For gethostbyname() #include "mDNSEmbeddedAPI.h" // Defines the interface to the client layer above @@ -326,7 +328,7 @@ mDNSexport int main(int argc, char **argv) mDNS_Init_NoCache, mDNS_Init_ZeroCacheSize, mDNS_Init_DontAdvertiseLocalAddresses, mDNS_Init_NoInitCallback, mDNS_Init_NoInitCallbackContext); - if (status) { fprintf(stderr, "Daemon start: mDNS_Init failed %ld\n", status); return(status); } + if (status) { fprintf(stderr, "Daemon start: mDNS_Init failed %d\n", (int)status); return(status); } mDNSPosixListenForSignalInEventLoop(SIGINT); mDNSPosixListenForSignalInEventLoop(SIGTERM); diff --git a/mDNSPosix/ReadMe.txt b/mDNSPosix/ReadMe.txt index 35be2b1..d4bff85 100755 --- a/mDNSPosix/ReadMe.txt +++ b/mDNSPosix/ReadMe.txt @@ -274,9 +274,7 @@ because I don't have access to the physical machine. Licencing --------- -This code is distributed under the Apple Public Source License. -Information about the licence is included at the top of each source file. - +This source code is Open Source; for details see the "LICENSE" file. Credits and Version History --------------------------- diff --git a/mDNSPosix/Responder.c b/mDNSPosix/Responder.c index 986333b..4f6b186 100755 --- a/mDNSPosix/Responder.c +++ b/mDNSPosix/Responder.c @@ -2,28 +2,27 @@ * * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: Responder.c,v $ +Revision 1.32 2006/08/14 23:24:46 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + +Revision 1.31 2006/06/12 18:22:42 cheshire + mDNSResponder building warnings under Red Hat 64-bit (LP64) Linux + Revision 1.30 2005/10/26 22:21:16 cheshire Potential buffer overflow in mDNSResponderPosix @@ -832,7 +831,7 @@ int main(int argc, char **argv) result = 2; } if ( (result != 0) || (gMDNSPlatformPosixVerboseLevel > 0) ) { - fprintf(stderr, "%s: Finished with status %ld, result %d\n", gProgramName, status, result); + fprintf(stderr, "%s: Finished with status %d, result %d\n", gProgramName, (int)status, result); } return result; diff --git a/mDNSPosix/dnsextd.c b/mDNSPosix/dnsextd.c index ab1071d..64895ab 100644 --- a/mDNSPosix/dnsextd.c +++ b/mDNSPosix/dnsextd.c @@ -2,52 +2,27 @@ * * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: dnsextd.c,v $ -Revision 1.41 2005/09/24 01:10:54 cheshire -Fix comment typos - -Revision 1.40 2005/09/07 21:54:37 ksekar - dnsextd doesn't clean up on exit -Close sockets before cleanup so clients can't make new requests - -Revision 1.39 2005/08/22 23:30:30 ksekar - memory leak in dnsextd.c - -Revision 1.38 2005/06/29 10:03:56 cheshire -Fix compile errors and warnings - -Revision 1.37 2005/06/27 22:12:17 ksekar - dnsextd performance improvements - -Revision 1.36 2005/06/14 23:14:41 ksekar - Unable to refresh LLQs +Revision 1.33.2.2 2006/08/29 06:24:34 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 -Revision 1.35 2005/03/17 03:57:43 cheshire -LEASE_OPT_SIZE is now LEASE_OPT_RDLEN; LLQ_OPT_SIZE is now LLQ_OPT_RDLEN - -Revision 1.34 2005/03/16 18:47:37 ksekar - dnsextd doesn't clean up on exit +Revision 1.33.2.1 2005/08/05 21:14:00 ksekar + Long-lived queries not working on windows +Change constant names Revision 1.33 2005/03/11 19:09:02 ksekar Fixed ZERO_LLQID macro @@ -177,7 +152,6 @@ Revision 1.1 2004/08/11 00:43:26 ksekar #include #include #include -#include #include #include @@ -255,9 +229,7 @@ typedef struct AnswerListElem mDNSu16 type; CacheRecord *KnownAnswers; // All valid answers delivered to client CacheRecord *EventList; // New answers (adds/removes) to be sent to client - int refcount; - mDNSBool UseTCP; // Use TCP if UDP would cause truncation - pthread_t tid; // Allow parallel list updates + int refcount; } AnswerListElem; // llq table entry @@ -278,7 +250,7 @@ typedef struct LLQEntry typedef struct { // server variables - read only after initialization (no locking) - struct sockaddr_in saddr; // server address + struct in_addr saddr; // server address domainname zone; // zone being updated int tcpsd; // listening TCP socket int udpsd; // listening UDP socket @@ -296,9 +268,8 @@ typedef struct // LLQ table variables LLQEntry *LLQTable[LLQ_TABLESIZE]; // !!!KRS change this and RRTable to use a common data structure AnswerListElem *AnswerTable[LLQ_TABLESIZE]; - int AnswerTableCount; - int LLQEventNotifySock; // Unix domain socket pair - update handling thread writes to EventNotifySock, which wakes - int LLQEventListenSock; // the main thread listening on EventListenSock, indicating that the zone has changed + int LLQEventListenSock; // Unix domain socket pair - polling thread writes to ServPollSock, which wakes + int LLQServPollSock; // the main thread listening on EventListenSock, indicating that the zone has changed } DaemonInfo; // args passed to UDP request handler thread as void* @@ -317,13 +288,6 @@ typedef struct DaemonInfo *d; } TCPRequestArgs; -// args passed to UpdateAnswerList thread as void* -typedef struct - { - DaemonInfo *d; - AnswerListElem *a; - } UpdateAnswerListArgs; - // // Global Variables // @@ -385,12 +349,11 @@ mDNSlocal void Log(const char *format, ...) // Error Logging // prints message "dnsextd : - " -// must be compiled w/ -D_REENTRANT for thread-safe errno usage +// must be compiled w/ -D_REENTRANT for thread-safe errno usage mDNSlocal void LogErr(const char *fn, const char *operation) { - char buf[512], errbuf[256]; - strerror_r(errno, errbuf, sizeof(errbuf)); - snprintf(buf, sizeof(buf), "%s: %s - %s", fn, operation, errbuf); + char buf[512]; + snprintf(buf, sizeof(buf), "%s: %s - %s", fn, operation, strerror(errno)); PrintLog(buf); } @@ -433,40 +396,30 @@ mDNSlocal void HdrHToN(PktMsg *pkt) // caller terminates connection via close() mDNSlocal int ConnectToServer(DaemonInfo *d) { - int ntries = 0, retry = 0; - - while (1) - { - int sd = socket(AF_INET, SOCK_STREAM, 0); - if (sd < 0) { LogErr("ConnectToServer", "socket"); return -1; } - if (!connect(sd, (struct sockaddr *)&d->saddr, sizeof(d->saddr))) return sd; - close(sd); - if (++ntries < 10) - { - LogErr("ConnectToServer", "connect"); - Log("ConnectToServer - retrying connection"); - if (!retry) retry = 500000 + random() % 500000; - usleep(retry); - retry *= 2; - } - else { Log("ConnectToServer - %d failed attempts. Aborting.", ntries); return -1; } - } + struct sockaddr_in servaddr; + int sd; + + bzero(&servaddr, sizeof(servaddr)); + if (d->saddr.s_addr) servaddr.sin_addr = d->saddr; + else inet_pton(AF_INET, LOOPBACK, &d->saddr); // use loopback if server not explicitly specified + servaddr.sin_port = htons(NS_PORT); + servaddr.sin_family = AF_INET; +#ifndef NOT_HAVE_SA_LEN + servaddr.sin_len = sizeof(servaddr); +#endif + sd = socket(AF_INET, SOCK_STREAM, 0); + if (sd < 0) { LogErr("ConnectToServer", "socket"); return -1; } + if (connect(sd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) { LogErr("ConnectToServer", "connect"); return -1; } + return sd; } -// send an entire block of data over a connected socket +// send an entire block of data over a connected socket, blocking if buffers are full mDNSlocal int MySend(int sd, const void *msg, int len) { - int selectval, n, nsent = 0; - fd_set wset; - struct timeval timeout = { 3, 0 }; // until we remove all calls from main thread, keep timeout short - + int n, nsent = 0; + while (nsent < len) { - FD_ZERO(&wset); - FD_SET(sd, &wset); - selectval = select(sd+1, NULL, &wset, NULL, &timeout); - if (selectval < 0) { LogErr("MySend", "select"); return -1; } - if (!selectval || !FD_ISSET(sd, &wset)) { Log("MySend - timeout"); return -1; } n = send(sd, (char *)msg + nsent, len - nsent, 0); if (n < 0) { LogErr("MySend", "send"); return -1; } nsent += n; @@ -493,21 +446,11 @@ static int my_recv(const int sd, void *const buf, const int len) // use an explicit while() loop instead. // Also, don't try to do '+=' arithmetic on the original "void *" pointer -- // arithmetic on "void *" pointers is compiler-dependent. - - fd_set rset; - struct timeval timeout = { 3, 0 }; // until we remove all calls from main thread, keep timeout short - int selectval, remaining = len; + int remaining = len; char *ptr = (char *)buf; - ssize_t num_read; - - while (remaining) + while (remaining) { - FD_ZERO(&rset); - FD_SET(sd, &rset); - selectval = select(sd+1, &rset, NULL, NULL, &timeout); - if (selectval < 0) { LogErr("my_recv", "select"); return -1; } - if (!selectval || !FD_ISSET(sd, &rset)) { Log("my_recv - timeout"); return -1; } - num_read = recv(sd, ptr, remaining, 0); + ssize_t num_read = recv(sd, ptr, remaining, 0); if ((num_read == 0) || (num_read < 0) || (num_read > remaining)) return -1; ptr += num_read; remaining -= num_read; @@ -528,7 +471,7 @@ mDNSlocal PktMsg *ReadTCPMsg(int sd, PktMsg *storage) unsigned int srclen; nread = my_recv(sd, &msglen, sizeof(msglen)); - if (nread < 0) { LogErr("ReadTCPMsg", "recv"); goto error; } + if (nread < 0) { LogErr("TCPRequestForkFn", "recv"); goto error; } msglen = ntohs(msglen); if (nread != sizeof(msglen)) { Log("Could not read length field of message"); goto error; } @@ -552,7 +495,7 @@ mDNSlocal PktMsg *ReadTCPMsg(int sd, PktMsg *storage) if (getpeername(sd, (struct sockaddr *)&pkt->src, &srclen) || srclen != sizeof(pkt->src)) { LogErr("ReadTCPMsg", "getpeername"); bzero(&pkt->src, sizeof(pkt->src)); } nread = my_recv(sd, &pkt->msg, msglen); - if (nread < 0) { LogErr("ReadTCPMsg", "recv"); goto error; } + if (nread < 0) { LogErr("TCPRequestForkFn", "recv"); goto error; } if (nread != msglen) { Log("Could not read entire message"); goto error; } if (pkt->len < sizeof(DNSMessageHeader)) { Log("ReadTCPMsg: Message too short (%d bytes)", pkt->len); goto error; } @@ -564,33 +507,6 @@ mDNSlocal PktMsg *ReadTCPMsg(int sd, PktMsg *storage) return NULL; } -mDNSlocal int UDPServerTransaction(const DaemonInfo *d, const PktMsg *request, PktMsg *reply, mDNSBool *trunc) - { - fd_set rset; - struct timeval timeout = { 3, 0 }; // until we remove all calls from main thread, keep timeout short - int selectval, err = -1, sd = socket(AF_INET, SOCK_DGRAM, 0); - - *trunc = mDNSfalse; - if (sd < 0) { LogErr("UDPServerTransaction", "socket"); goto end; } - if (sendto(sd, (char *)&request->msg, request->len, 0, (struct sockaddr *)&d->saddr, sizeof(d->saddr)) != (int)request->len) - { LogErr("UDPServerTransaction", "sendto"); goto end; } - - FD_ZERO(&rset); - FD_SET(sd, &rset); - selectval = select(sd+1, &rset, NULL, NULL, &timeout); - if (selectval < 0) { LogErr("UDPServerTransaction", "select"); goto end; } - if (!selectval || !FD_ISSET(sd, &rset)) { Log("UDPServerTransaction - timeout"); goto end; } - reply->len = recvfrom(sd, &reply->msg, sizeof(reply->msg), 0, NULL, NULL); - if ((int)reply->len < 0) { LogErr("UDPServerTransaction", "recvfrom"); goto end; } - if (reply->len < sizeof(DNSMessageHeader)) { Log("UDPServerTransaction - Message too short (%d bytes)", reply->len); goto end; } - if (reply->msg.h.flags.b[0] & kDNSFlag0_TC) *trunc = mDNStrue; - err = 0; - - end: - if (sd >= 0) close(sd); - return err; - } - // // Dynamic Update Utility Routines // @@ -926,14 +842,10 @@ mDNSlocal void PrintHelp(void) mDNSlocal int ProcessArgs(int argc, char *argv[], DaemonInfo *d) { int opt; - struct in_addr server; - + if (argc < 2) goto arg_error; - - // defaults, may be overriden by command option - d->port.NotAnInteger = htons(DAEMON_PORT); - inet_pton(AF_INET, LOOPBACK, &server); // use loopback if server not explicitly specified + d->port.NotAnInteger = htons(DAEMON_PORT); // default, may be overriden by command option while ((opt = getopt(argc, argv, "z:p:hfvs:k:")) != -1) { switch(opt) @@ -944,8 +856,8 @@ mDNSlocal int ProcessArgs(int argc, char *argv[], DaemonInfo *d) case 'h': PrintHelp(); return -1; case 'f': foreground = 1; break; case 'v': verbose = 1; break; - case 's': if (!inet_pton(AF_INET, optarg, &server)) goto arg_error; - break; + case 's': if (!inet_pton(AF_INET, optarg, &d->saddr)) goto arg_error; + break; case 'k': if (ReadAuthKey(argc, argv, d) < 0) goto arg_error; break; case 'z': if (!MakeDomainNameFromDNSNameString(&d->zone, optarg)) @@ -960,16 +872,6 @@ mDNSlocal int ProcessArgs(int argc, char *argv[], DaemonInfo *d) if (!d->zone.c[0]) goto arg_error; // zone is the only required argument if (d->AuthInfo) AssignDomainName(&d->AuthInfo->zone, &d->zone); // if we have a shared secret, use it for the entire zone - - // setup server's sockaddr - bzero(&d->saddr, sizeof(d->saddr)); - d->saddr.sin_addr = server; - d->saddr.sin_port = htons(NS_PORT); - d->saddr.sin_family = AF_INET; -#ifndef NOT_HAVE_SA_LEN - d->saddr.sin_len = sizeof(d->saddr); -#endif - return 0; arg_error: @@ -1018,7 +920,7 @@ mDNSlocal int SetupSockets(DaemonInfo *daemon) // set up Unix domain socket pair for LLQ polling thread to signal main thread that a change to the zone occurred if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sockpair) < 0) { LogErr("SetupSockets", "socketpair"); return -1; } daemon->LLQEventListenSock = sockpair[0]; - daemon->LLQEventNotifySock = sockpair[1]; + daemon->LLQServPollSock = sockpair[1]; return 0; } @@ -1027,9 +929,9 @@ mDNSlocal int SetupSockets(DaemonInfo *daemon) // // Delete a resource record from the nameserver via a dynamic update -// sd is a socket already connected to the server -mDNSlocal void DeleteOneRecord(DaemonInfo *d, CacheRecord *rr, domainname *zone, int sd) +mDNSlocal void DeleteRecord(DaemonInfo *d, CacheRecord *rr, domainname *zone) { + int sd = -1; mDNSOpaque16 id; PktMsg pkt; mDNSu8 *ptr = pkt.msg.data; @@ -1039,6 +941,8 @@ mDNSlocal void DeleteOneRecord(DaemonInfo *d, CacheRecord *rr, domainname *zone, PktMsg *reply = NULL; VLog("Expiring record %s", GetRRDisplayString_rdb(&rr->resrec, &rr->resrec.rdata->u, buf)); + sd = ConnectToServer(d); + if (sd < 0) { Log("DeleteRecord: ConnectToServer failed"); goto end; } id.NotAnInteger = 0; InitializeDNSMessage(&pkt.msg.h, id, UpdateReqFlags); @@ -1060,45 +964,51 @@ mDNSlocal void DeleteOneRecord(DaemonInfo *d, CacheRecord *rr, domainname *zone, pkt.len = ptr - (mDNSu8 *)&pkt.msg; pkt.src.sin_addr.s_addr = htonl(INADDR_ANY); // address field set solely for verbose logging in subroutines pkt.src.sin_family = AF_INET; - if (SendTCPMsg(sd, &pkt)) { Log("DeleteOneRecord: SendTCPMsg failed"); } + if (SendTCPMsg(sd, &pkt)) { Log("DeleteRecord: SendTCPMsg failed"); } reply = ReadTCPMsg(sd, NULL); if (!SuccessfulUpdateTransaction(&pkt, reply)) - Log("Expiration update failed with rcode %d", reply ? reply->msg.h.flags.b[1] & kDNSFlag1_RC : -1); + Log("Expiration update failed with rcode %d", reply->msg.h.flags.b[1] & kDNSFlag1_RC); end: - if (!ptr) { Log("DeleteOneRecord: Error constructing lease expiration update"); } + if (!ptr) { Log("DeleteRecord: Error constructing lease expiration update"); } + if (sd >= 0) close(sd); if (reply) free(reply); } -// iterate over table, deleting expired records (or all records if DeleteAll is true) -mDNSlocal void DeleteRecords(DaemonInfo *d, mDNSBool DeleteAll) +// iterate over table, deleting expired records +mDNSlocal void DeleteExpiredRecords(DaemonInfo *d) { + int i; + RRTableElem *ptr, *prev, *fptr; struct timeval now; - int i, sd = ConnectToServer(d); - if (sd < 0) { Log("DeleteRecords: ConnectToServer failed"); return; } - if (gettimeofday(&now, NULL)) { LogErr("DeleteRecords ", "gettimeofday"); return; } - if (pthread_mutex_lock(&d->tablelock)) { LogErr("DeleteRecords", "pthread_mutex_lock"); return; } + if (gettimeofday(&now, NULL)) { LogErr("DeleteExpiredRecords ", "gettimeofday"); return; } + if (pthread_mutex_lock(&d->tablelock)) { LogErr("DeleteExpiredRecords", "pthread_mutex_lock"); return; } for (i = 0; i < d->nbuckets; i++) { - RRTableElem **ptr = &d->table[i]; - while (*ptr) + ptr = d->table[i]; + prev = NULL; + while (ptr) { - if (DeleteAll || (*ptr)->expire - now.tv_sec < 0) + if (ptr->expire - now.tv_sec < 0) { - RRTableElem *fptr; // delete record from server - DeleteOneRecord(d, &(*ptr)->rr, &(*ptr)->zone, sd); - fptr = *ptr; - *ptr = (*ptr)->next; + DeleteRecord(d, &ptr->rr, &ptr->zone); + if (prev) prev->next = ptr->next; + else d->table[i] = ptr->next; + fptr = ptr; + ptr = ptr->next; free(fptr); d->nelems--; } - else ptr = &(*ptr)->next; + else + { + prev = ptr; + ptr = ptr->next; + } } } pthread_mutex_unlock(&d->tablelock); - close(sd); } // @@ -1235,54 +1145,32 @@ mDNSlocal PktMsg *FormatLeaseReply(DaemonInfo *d, PktMsg *orig, mDNSu32 lease) mDNSlocal PktMsg *HandleRequest(PktMsg *pkt, DaemonInfo *d) { int sd = -1; - PktMsg *reply = NULL, *LeaseReply, buf; + PktMsg *reply = NULL, *LeaseReply; mDNSs32 lease; - char addrbuf[32], pingmsg[4]; + char buf[32]; // send msg to server, read reply - - if (pkt->len <= 512) - { - mDNSBool trunc; - if (UDPServerTransaction(d, pkt, &buf, &trunc) < 0) - Log("HandleRequest - UDPServerTransaction failed. Trying TCP"); - else if (trunc) VLog("HandleRequest - answer truncated. Using TCP"); - else reply = &buf; // success - } - - if (!reply) - { - sd = ConnectToServer(d); - if (sd < 0) - { Log("Discarding request from %s due to connection errors", inet_ntop(AF_INET, &pkt->src.sin_addr, addrbuf, 32)); goto cleanup; } - if (SendTCPMsg(sd, pkt) < 0) - { Log("Couldn't relay message from %s to server. Discarding.", inet_ntop(AF_INET, &pkt->src.sin_addr, addrbuf, 32)); goto cleanup; } - reply = ReadTCPMsg(sd, &buf); - } - + sd = ConnectToServer(d); + if (sd < 0) + { Log("Discarding request from %s due to connection errors", inet_ntop(AF_INET, &pkt->src.sin_addr, buf, 32)); goto cleanup; } + if (SendTCPMsg(sd, pkt) < 0) + { Log("Couldn't relay message from %s to server. Discarding.", inet_ntop(AF_INET, &pkt->src.sin_addr, buf, 32)); goto cleanup; } + reply = ReadTCPMsg(sd, NULL); + // process reply if (!SuccessfulUpdateTransaction(pkt, reply)) - { VLog("Message from %s not a successful update.", inet_ntop(AF_INET, &pkt->src.sin_addr, addrbuf, 32)); goto cleanup; } + { VLog("Message from %s not a successful update.", inet_ntop(AF_INET, &pkt->src.sin_addr, buf, 32)); goto cleanup; } lease = GetPktLease(pkt); UpdateLeaseTable(pkt, d, lease); if (lease > 0) { LeaseReply = FormatLeaseReply(d, reply, lease); if (!LeaseReply) Log("HandleRequest - unable to format lease reply"); + free(reply); reply = LeaseReply; } - - // tell the main thread there was an update so it can send LLQs - if (send(d->LLQEventNotifySock, pingmsg, sizeof(pingmsg), 0) != sizeof(pingmsg)) LogErr("HandleRequest", "send"); - cleanup: if (sd >= 0) close(sd); - if (reply == &buf) - { - reply = malloc(sizeof(*reply)); - if (!reply) LogErr("HandleRequest", "malloc"); - else { reply->len = buf.len; memcpy(&reply->msg, &buf.msg, buf.len); } - } return reply; } @@ -1327,13 +1215,9 @@ mDNSlocal void DeleteLLQ(DaemonInfo *d, LLQEntry *e) inet_ntop(AF_INET, &e->cli.sin_addr, addr, 32); VLog("Deleting LLQ table entry for %##s client %s", e->qname.c, addr); - if (a && !(--a->refcount) && d->AnswerTableCount >= LLQ_TABLESIZE) + // free shared answer structure if ref count drops to zero + if (a && !(--a->refcount)) { - // currently, generating initial answers blocks the main thread, so we keep the answer list - // even if the ref count drops to zero. To prevent unbounded table growth, we free shared answers - // if the ref count drops to zero AND there are more table elements than buckets - // !!!KRS update this when we make the table dynamically growable - CacheRecord *cr = a->KnownAnswers, *tmp; AnswerListElem **tbl = &d->AnswerTable[bucket]; @@ -1345,7 +1229,7 @@ mDNSlocal void DeleteLLQ(DaemonInfo *d, LLQEntry *e) } while (*tbl && *tbl != a) tbl = &(*tbl)->next; - if (*tbl) { *tbl = (*tbl)->next; free(a); d->AnswerTableCount--; } + if (*tbl) { *tbl = (*tbl)->next; free(a); } else Log("Error: DeleteLLQ - AnswerList not found in table"); } @@ -1372,17 +1256,20 @@ mDNSlocal int SendLLQ(DaemonInfo *d, PktMsg *pkt, struct sockaddr_in dst) return err; } -mDNSlocal CacheRecord *AnswerQuestion(DaemonInfo *d, AnswerListElem *e) +// if non-negative, sd is a TCP socket connected to the nameserver +// otherwise, this routine creates and closes its own socket +mDNSlocal CacheRecord *AnswerQuestion(DaemonInfo *d, AnswerListElem *e, int sd) { PktMsg q; - int i, sd = -1; + int i; const mDNSu8 *ansptr; mDNSu8 *end = q.msg.data; mDNSOpaque16 id, flags = QueryFlags; - PktMsg buf, *reply = NULL; + PktMsg *reply = NULL; LargeCacheRecord lcr; CacheRecord *AnswerList = NULL; mDNSu8 rcode; + mDNSBool CloseSDOnExit = sd < 0; VLog("Querying server for %##s type %d", e->name.c, e->type); @@ -1393,26 +1280,11 @@ mDNSlocal CacheRecord *AnswerQuestion(DaemonInfo *d, AnswerListElem *e) end = putQuestion(&q.msg, end, end + AbsoluteMaxDNSMessageData, &e->name, e->type, kDNSClass_IN); if (!end) { Log("Error: AnswerQuestion - putQuestion returned NULL"); goto end; } q.len = (int)(end - (mDNSu8 *)&q.msg); - - if (!e->UseTCP) - { - mDNSBool trunc; - - if (UDPServerTransaction(d, &q, &buf, &trunc) < 0) - Log("AnswerQuestion %##s - UDPServerTransaction failed. Trying TCP", e->name.c); - else if (trunc) - { VLog("AnswerQuestion %##s - answer truncated. Using TCP", e->name.c); e->UseTCP = mDNStrue; } - else reply = &buf; // success - } - if (!reply) - { - sd = ConnectToServer(d); - if (sd < 0) { Log("AnswerQuestion: ConnectToServer failed"); goto end; } - if (SendTCPMsg(sd, &q)) { Log("AnswerQuestion: SendTCPMsg failed"); close(sd); goto end; } - reply = ReadTCPMsg(sd, NULL); - close(sd); - } + if (sd < 0) sd = ConnectToServer(d); + if (sd < 0) { Log("AnswerQuestion: ConnectToServer failed"); goto end; } + if (SendTCPMsg(sd, &q)) { Log("AnswerQuestion: SendTCPMsg failed"); close(sd); goto end; } + reply = ReadTCPMsg(sd, NULL); if ((reply->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask) != (kDNSFlag0_QR_Response | kDNSFlag0_OP_StdQuery)) { Log("AnswerQuestion: %##s type %d - Invalid response flags from server"); goto end; } @@ -1442,22 +1314,18 @@ mDNSlocal CacheRecord *AnswerQuestion(DaemonInfo *d, AnswerListElem *e) } end: - if (reply && reply != &buf) free(reply); + if (sd > -1 && CloseSDOnExit) close(sd); + if (reply) free(reply); return AnswerList; } -// Routine forks a thread to set EventList to contain Add/Remove events, and deletes any removes from the KnownAnswer list -mDNSlocal void *UpdateAnswerList(void *args) +// Routine sets EventList to contain Add/Remove events, and deletes any removes from the KnownAnswer list +mDNSlocal void UpdateAnswerList(DaemonInfo *d, AnswerListElem *a, int sd) { CacheRecord *cr, *NewAnswers, **na, **ka; // "new answer", "known answer" - DaemonInfo *d = ((UpdateAnswerListArgs *)args)->d; - AnswerListElem *a = ((UpdateAnswerListArgs *)args)->a; - free(args); - args = NULL; - // get up to date answers - NewAnswers = AnswerQuestion(d, a); + NewAnswers = AnswerQuestion(d, a, sd); // first pass - mark all answers for deletion for (ka = &a->KnownAnswers; *ka; ka = &(*ka)->next) @@ -1511,9 +1379,7 @@ mDNSlocal void *UpdateAnswerList(void *args) cr = NewAnswers; NewAnswers = NewAnswers->next; free(cr); - } - - return NULL; + } } mDNSlocal void SendEvents(DaemonInfo *d, LLQEntry *e) @@ -1537,7 +1403,7 @@ mDNSlocal void SendEvents(DaemonInfo *d, LLQEntry *e) if (verbose) GetRRDisplayString_rdb(&cr->resrec, &cr->resrec.rdata->u, rrbuf); VLog("%s (%s): %s", addrbuf, (mDNSs32)cr->resrec.rroriginalttl < 0 ? "Remove": "Add", rrbuf); end = PutResourceRecordTTLJumbo(&response.msg, end, &response.msg.h.numAnswers, &cr->resrec, cr->resrec.rroriginalttl); - if (!end) { Log("Error: SendEvents - PutResourceRecordTTLJumbo returned NULL"); return; } + if (!end) { Log("Error: SendEvents - UpdateAnswerList returned NULL"); return; } } FormatLLQOpt(&opt, kLLQOp_Event, e->id, LLQLease(e)); @@ -1548,28 +1414,6 @@ mDNSlocal void SendEvents(DaemonInfo *d, LLQEntry *e) if (SendLLQ(d, &response, e->cli) < 0) LogMsg("Error: SendEvents - SendLLQ"); } -mDNSlocal void PrintLLQAnswers(DaemonInfo *d) - { - int i; - char rrbuf[80]; - - Log("Printing LLQ Answer Table contents"); - - for (i = 0; i < LLQ_TABLESIZE; i++) - { - AnswerListElem *a = d->AnswerTable[i]; - while(a) - { - int ancount = 0; - const CacheRecord *rr = a->KnownAnswers; - while (rr) { ancount++; rr = rr->next; } - Log("%p : Question %##s; type %d; referenced by %d LLQs; %d answers:", a, a->name.c, a->type, a->refcount, ancount); - for (rr = a->KnownAnswers; rr; rr = rr->next) Log("\t%s", GetRRDisplayString_rdb(&rr->resrec, &rr->resrec.rdata->u, rrbuf)); - a = a->next; - } - } - } - mDNSlocal void PrintLLQTable(DaemonInfo *d) { LLQEntry *e; @@ -1583,19 +1427,9 @@ mDNSlocal void PrintLLQTable(DaemonInfo *d) e = d->LLQTable[i]; while(e) { - char *state; - - switch (e->state) - { - case RequestReceived: state = "RequestReceived"; break; - case ChallengeSent: state = "ChallengeSent"; break; - case Established: state = "Established"; break; - default: state = "unknown"; - } - inet_ntop(AF_INET, &e->cli.sin_addr, addr, 32); - - Log("LLQ from %s in state %s; %##s; type %d; orig lease %d; remaining lease %d; AnswerList %p)", - addr, state, e->qname.c, e->qtype, e->lease, LLQLease(e), e->AnswerList); + inet_ntop(AF_INET, &e->cli.sin_addr, addr, 32); + Log("LLQ from %##s type %d lease %d (%d remaining)", + addr, e->qname.c, e->qtype, e->lease, LLQLease(e)); e = e->next; } } @@ -1605,13 +1439,14 @@ mDNSlocal void PrintLLQTable(DaemonInfo *d) mDNSlocal void GenLLQEvents(DaemonInfo *d) { LLQEntry **e; - int i; + int i, sd; struct timeval t; - UpdateAnswerListArgs *args; - + VLog("Generating LLQ Events"); gettimeofday(&t, NULL); + sd = ConnectToServer(d); + if (sd < 0) { Log("GenLLQEvents: ConnectToServer failed"); return; } // get all answers up to date for (i = 0; i < LLQ_TABLESIZE; i++) @@ -1619,26 +1454,11 @@ mDNSlocal void GenLLQEvents(DaemonInfo *d) AnswerListElem *a = d->AnswerTable[i]; while(a) { - args = malloc(sizeof(*args)); - if (!args) { LogErr("GenLLQEvents", "malloc"); return; } - args->d = d; - args->a = a; - if (pthread_create(&a->tid, NULL, UpdateAnswerList, args) < 0) { LogErr("GenLLQEvents", "pthread_create"); return; } - usleep(1); + UpdateAnswerList(d, a, sd); a = a->next; } } - for (i = 0; i < LLQ_TABLESIZE; i++) - { - AnswerListElem *a = d->AnswerTable[i]; - while(a) - { - if (pthread_join(a->tid, NULL)) LogErr("GenLLQEvents", "pthread_join"); - a = a->next; - } - } - // for each established LLQ, send events for (i = 0; i < LLQ_TABLESIZE; i++) { @@ -1680,6 +1500,79 @@ mDNSlocal void GenLLQEvents(DaemonInfo *d) a = a->next; } } + + close(sd); + } + +// Monitor zone for changes that may produce LLQ events +mDNSlocal void *LLQEventMonitor(void *DInfoPtr) + { + DaemonInfo *d = DInfoPtr; + PktMsg q; + mDNSu8 *end = q.msg.data; + const mDNSu8 *ptr; + mDNSOpaque16 id, flags = QueryFlags; + PktMsg reply; + mDNSs32 serial = 0; + mDNSBool SerialInitialized = mDNSfalse; + int sd; + LargeCacheRecord lcr; + ResourceRecord *rr = &lcr.r.resrec; + int i, sleeptime = 0; + domainname zone; + char pingmsg[4]; + + // create question + id.NotAnInteger = 0; + InitializeDNSMessage(&q.msg.h, id, flags); + AssignDomainName(&zone, &d->zone); + end = putQuestion(&q.msg, end, end + AbsoluteMaxDNSMessageData, &zone, kDNSType_SOA, kDNSClass_IN); + if (!end) { Log("Error: LLQEventMonitor - putQuestion returned NULL"); return NULL; } + q.len = (int)(end - (mDNSu8 *)&q.msg); + + sd = ConnectToServer(d); + if (sd < 0) { Log("LLQEventMonitor: ConnectToServer failed"); return NULL; } + + while(1) + { + usleep(sleeptime); + sleeptime = LLQ_MONITOR_ERR_INTERVAL; // if we bail on error below, rate limit retry + + // send message, receive response + if (SendTCPMsg(sd, &q)) { Log("LLQEventMonitor: SendTCPMsg failed"); continue; } + if (!ReadTCPMsg(sd, &reply)) { Log("LLQEventMonitor: ReadTCPMsg failed"); continue; } + end = (mDNSu8 *)&reply.msg + reply.len; + if (reply.msg.h.flags.b[1] & kDNSFlag1_RC) { Log("LLQEventMonitor - received non-zero rcode"); continue; } + + // find answer + ptr = LocateAnswers(&reply.msg, end); + if (!ptr) { Log("Error: LLQEventMonitor - LocateAnswers returned NULL"); continue; } + for (i = 0; i < reply.msg.h.numAnswers; i++) + { + ptr = GetLargeResourceRecord(NULL, &reply.msg, ptr, end, 0, kDNSRecordTypePacketAns, &lcr); + if (!ptr) { Log("Error: LLQEventMonitor - GetLargeResourceRecord returned NULL"); continue; } + if (rr->rrtype != kDNSType_SOA || rr->rrclass != kDNSClass_IN || !SameDomainName(rr->name, &zone)) continue; + if (!SerialInitialized) + { + // first time through loop + SerialInitialized = mDNStrue; + serial = rr->rdata->u.soa.serial; + sleeptime = LLQ_MONITOR_INTERVAL; + break; + } + else if (rr->rdata->u.soa.serial != serial) + { + // update serial, wake main thread + serial = rr->rdata->u.soa.serial; + VLog("LLQEventMonitor: zone changed. Signaling main thread."); + if (send(d->LLQServPollSock, pingmsg, sizeof(pingmsg), 0) != sizeof(pingmsg)) + { LogErr("LLQEventMonitor", "send"); break; } + } + sleeptime = LLQ_MONITOR_INTERVAL; + break; + } + if (!ptr) Log("LLQEventMonitor: response to query did not contain SOA"); + } } mDNSlocal void SetAnswerList(DaemonInfo *d, LLQEntry *e) @@ -1694,12 +1587,15 @@ mDNSlocal void SetAnswerList(DaemonInfo *d, LLQEntry *e) AssignDomainName(&a->name, &e->qname); a->type = e->qtype; a->refcount = 0; + a->KnownAnswers = NULL; a->EventList = NULL; - a->UseTCP = mDNSfalse; a->next = d->AnswerTable[bucket]; d->AnswerTable[bucket] = a; - d->AnswerTableCount++; - a->KnownAnswers = AnswerQuestion(d, a); + + // to get initial answer list, call UpdateAnswerList and move cache records from EventList to KnownAnswers + UpdateAnswerList(d, a, -1); + a->KnownAnswers = a->EventList; + a->EventList = NULL; } e->AnswerList = a; @@ -1754,11 +1650,8 @@ mDNSlocal void LLQRefresh(DaemonInfo *d, LLQEntry *e, LLQOptData *llq, mDNSOpaqu if (llq->lease) { - struct timeval t; if (llq->lease < LLQ_MIN_LEASE) llq->lease = LLQ_MIN_LEASE; else if (llq->lease > LLQ_MAX_LEASE) llq->lease = LLQ_MIN_LEASE; - gettimeofday(&t, NULL); - e->expire = t.tv_sec + llq->lease; } ack.src.sin_addr.s_addr = 0; // unused @@ -2090,7 +1983,6 @@ mDNSlocal void *TCPRequestForkFn(void *vptr) } cleanup: - close(req->sd); free(req); if (in) free(in); if (out) free(out); @@ -2099,34 +1991,31 @@ mDNSlocal void *TCPRequestForkFn(void *vptr) mDNSlocal int RecvTCPRequest(int sd, DaemonInfo *d) { - TCPRequestArgs *req = NULL; + TCPRequestArgs *req; pthread_t tid; unsigned int clilen = sizeof(req->cliaddr); req = malloc(sizeof(TCPRequestArgs)); - if (!req) { LogErr("RecvTCPRequest", "malloc"); goto error; } + if (!req) { LogErr("RecvTCPRequest", "malloc"); return -1; } bzero(req, sizeof(*req)); req->d = d; req->sd = accept(sd, (struct sockaddr *)&req->cliaddr, &clilen); - if (req->sd < 0) { LogErr("RecvTCPRequest", "accept"); goto error; } - if (clilen != sizeof(req->cliaddr)) { Log("Client address of unknown size %d", clilen); goto error; } - if (pthread_create(&tid, NULL, TCPRequestForkFn, req)) { LogErr("RecvTCPRequest", "pthread_create"); goto error; } + if (req->sd < 0) { LogErr("RecvTCPRequest", "accept"); return -1; } + if (clilen != sizeof(req->cliaddr)) { Log("Client address of unknown size %d", clilen); free(req); return -1; } + if (pthread_create(&tid, NULL, TCPRequestForkFn, req)) { LogErr("RecvTCPRequest", "pthread_create"); free(req); return -1; } pthread_detach(tid); return 0; - - error: - if (req) free(req); - return -1; } // main event loop // listen for incoming requests, periodically check table for expired records, respond to signals mDNSlocal int ListenForUpdates(DaemonInfo *d) { - int maxfdp1, nfds; + int err; + int maxfdp1; fd_set rset; - struct timeval timenow, timeout, EventTS, tablecheck = { 0, 0 }; - mDNSBool EventsPending = mDNSfalse; + struct timeval timenow, timeout = { 0, 0 }; + long NextTableCheck = 0; VLog("Listening for requests..."); @@ -2137,72 +2026,42 @@ mDNSlocal int ListenForUpdates(DaemonInfo *d) while(1) { - // set timeout - timeout.tv_sec = timeout.tv_usec = 0; + // expire records if necessary, set timeout if (gettimeofday(&timenow, NULL)) { LogErr("ListenForUpdates", "gettimeofday"); return -1; } - if (EventsPending) + if (timenow.tv_sec >= NextTableCheck) { - if (timenow.tv_sec - EventTS.tv_sec >= 5) // if we've been waiting 5 seconds for a "quiet" period to send - { GenLLQEvents(d); EventsPending = mDNSfalse; } // events, we go ahead and do it now - else timeout.tv_usec = 500000; // else do events after 1/2 second with no new events or LLQs - } - if (!EventsPending) - { - // if no pending events, timeout when we need to check for expired records - if (tablecheck.tv_sec && timenow.tv_sec - tablecheck.tv_sec >= 0) - { DeleteRecords(d, mDNSfalse); tablecheck.tv_sec = 0; } // table check overdue - if (!tablecheck.tv_sec) tablecheck.tv_sec = timenow.tv_sec + EXPIRATION_INTERVAL; - timeout.tv_sec = tablecheck.tv_sec - timenow.tv_sec; + DeleteExpiredRecords(d); + NextTableCheck = timenow.tv_sec + EXPIRATION_INTERVAL; } + timeout.tv_sec = NextTableCheck - timenow.tv_sec; FD_SET(d->tcpsd, &rset); FD_SET(d->udpsd, &rset); FD_SET(d->LLQEventListenSock, &rset); - nfds = select(maxfdp1, &rset, NULL, NULL, &timeout); - if (nfds < 0) + err = select(maxfdp1, &rset, NULL, NULL, &timeout); + if (err < 0) { if (errno == EINTR) { - if (terminate) - { - // close sockets to prevent clients from making new requests during shutdown - close(d->tcpsd); - close(d->udpsd); - d->tcpsd = d->udpsd = -1; - DeleteRecords(d, mDNStrue); - return 0; - } - else if (dumptable) { PrintLeaseTable(d); PrintLLQTable(d); PrintLLQAnswers(d); dumptable = 0; } + if (terminate) { DeleteExpiredRecords(d); return 0; } + else if (dumptable) { PrintLeaseTable(d); PrintLLQTable(d); dumptable = 0; } else Log("Received unhandled signal - continuing"); } - else - { - LogErr("ListenForUpdates", "select"); return -1; - } + else { LogErr("ListenForUpdates", "select"); return -1; } } - else if (nfds) + else { if (FD_ISSET(d->tcpsd, &rset)) RecvTCPRequest(d->tcpsd, d); if (FD_ISSET(d->udpsd, &rset)) RecvUDPRequest(d->udpsd, d); if (FD_ISSET(d->LLQEventListenSock, &rset)) { // clear signalling data off socket - char buf[256]; - recv(d->LLQEventListenSock, buf, 256, 0); - if (!EventsPending) - { - EventsPending = mDNStrue; - if (gettimeofday(&EventTS, NULL)) { LogErr("ListenForUpdates", "gettimeofday"); return -1; } - } + char buf[32]; + recv(d->LLQEventListenSock, buf, 32, 0); + GenLLQEvents(d); } } - else - { - // timeout - if (EventsPending) { GenLLQEvents(d); EventsPending = mDNSfalse; } - else { DeleteRecords(d, mDNSfalse); tablecheck.tv_sec = 0; } - } } return 0; } @@ -2217,26 +2076,17 @@ mDNSlocal void HndlSignal(int sig) int main(int argc, char *argv[]) { + pthread_t LLQtid; DaemonInfo *d; - struct rlimit rlim; - + d = malloc(sizeof(*d)); if (!d) { LogErr("main", "malloc"); exit(1); } - bzero(d, sizeof(DaemonInfo)); + bzero(d, sizeof(DaemonInfo)); if (signal(SIGTERM, HndlSignal) == SIG_ERR) perror("Can't catch SIGTERM"); if (signal(INFO_SIGNAL, HndlSignal) == SIG_ERR) perror("Can't catch SIGINFO"); if (signal(SIGINT, HndlSignal) == SIG_ERR) perror("Can't catch SIGINT"); if (signal(SIGPIPE, SIG_IGN ) == SIG_ERR) perror("Can't ignore SIGPIPE"); - - // remove open file limit - rlim.rlim_max = RLIM_INFINITY; - rlim.rlim_cur = RLIM_INFINITY; - if (setrlimit(RLIMIT_NOFILE, &rlim) < 0) - { - LogErr("main", "setrlimit"); - Log("Using default file descriptor resource limit"); - } if (ProcessArgs(argc, argv, d) < 0) exit(1); @@ -2253,8 +2103,14 @@ int main(int argc, char *argv[]) if (InitLeaseTable(d) < 0) exit(1); if (SetupSockets(d) < 0) exit(1); if (SetUpdateSRV(d) < 0) exit(1); - - ListenForUpdates(d); + + if (pthread_create(&LLQtid, NULL, LLQEventMonitor, d)) { LogErr("main", "pthread_create"); } + else + { + pthread_detach(LLQtid); + ListenForUpdates(d); + } + if (ClearUpdateSRV(d) < 0) exit(1); // clear update srv's even if ListenForUpdates or pthread_create returns an error free(d); exit(0); diff --git a/mDNSPosix/mDNSPosix.c b/mDNSPosix/mDNSPosix.c index 4b0ab0b..afa9a80 100755 --- a/mDNSPosix/mDNSPosix.c +++ b/mDNSPosix/mDNSPosix.c @@ -2,24 +2,17 @@ * * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ * * Formatting notes: * This code follows the "Whitesmiths style" C indentation rules. Plenty of discussion @@ -37,6 +30,18 @@ Change History (most recent first): $Log: mDNSPosix.c,v $ +Revision 1.78.2.1 2006/08/29 06:24:34 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + +Revision 1.78 2006/06/28 09:12:22 cheshire +Added debugging message + +Revision 1.77 2006/03/19 02:00:11 cheshire + Improve logic for delaying packets after repeated interface transitions + +Revision 1.76 2006/01/09 19:29:16 cheshire + Cap number of "sendto failed" messages we allow mDNSResponder to log + Revision 1.75 2006/01/05 22:04:57 cheshire Log error message when send fails with "operation not permitted" @@ -447,15 +452,20 @@ mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const ms if (err > 0) err = 0; else if (err < 0) { + static int MessageCount = 0; // Don't report EHOSTDOWN (i.e. ARP failure), ENETDOWN, or no route to host for unicast destinations if (!mDNSAddressIsAllDNSLinkGroup(dst)) if (errno == EHOSTDOWN || errno == ENETDOWN || errno == EHOSTUNREACH || errno == ENETUNREACH) return(mStatus_TransientErr); - if (thisIntf) - LogMsg("mDNSPlatformSendUDP got error %d (%s) sending packet to %#a on interface %#a/%s/%d", - errno, strerror(errno), dst, &thisIntf->coreIntf.ip, thisIntf->intfName, thisIntf->index); - else - LogMsg("mDNSPlatformSendUDP got error %d (%s) sending packet to %#a", errno, strerror(errno), dst); + if (MessageCount < 1000) + { + MessageCount++; + if (thisIntf) + LogMsg("mDNSPlatformSendUDP got error %d (%s) sending packet to %#a on interface %#a/%s/%d", + errno, strerror(errno), dst, &thisIntf->coreIntf.ip, thisIntf->intfName, thisIntf->index); + else + LogMsg("mDNSPlatformSendUDP got error %d (%s) sending packet to %#a", errno, strerror(errno), dst); + } } return PosixErrorToStatus(err); @@ -681,7 +691,7 @@ mDNSlocal PosixNetworkInterface *SearchForInterfaceByName(mDNS *const m, const c return intf; } -mDNSexport mDNSInterfaceID mDNSPlatformInterfaceIDfromInterfaceIndex(const mDNS *const m, mDNSu32 index) +mDNSexport mDNSInterfaceID mDNSPlatformInterfaceIDfromInterfaceIndex(mDNS *const m, mDNSu32 index) { PosixNetworkInterface *intf; @@ -696,7 +706,7 @@ mDNSexport mDNSInterfaceID mDNSPlatformInterfaceIDfromInterfaceIndex(const mDNS return (mDNSInterfaceID) intf; } -mDNSexport mDNSu32 mDNSPlatformInterfaceIndexfromInterfaceID(const mDNS *const m, mDNSInterfaceID id) +mDNSexport mDNSu32 mDNSPlatformInterfaceIndexfromInterfaceID(mDNS *const m, mDNSInterfaceID id) { PosixNetworkInterface *intf; @@ -732,7 +742,7 @@ mDNSlocal void ClearInterfaceList(mDNS *const m) while (m->HostInterfaces) { PosixNetworkInterface *intf = (PosixNetworkInterface*)(m->HostInterfaces); - mDNS_DeregisterInterface(m, &intf->coreIntf); + mDNS_DeregisterInterface(m, &intf->coreIntf, mDNSfalse); if (gMDNSPlatformPosixVerboseLevel > 0) fprintf(stderr, "Deregistered interface %s\n", intf->intfName); FreePosixNetworkInterface(intf); } @@ -884,6 +894,7 @@ mDNSlocal int SetupSocket(struct sockaddr *intfAddr, mDNSIPPort port, int interf { imr6.ipv6mr_multiaddr = *(const struct in6_addr*)&AllDNSLinkGroupv6; imr6.ipv6mr_interface = interfaceIndex; + //LogMsg("Joining %.16a on %d", &imr6.ipv6mr_multiaddr, imr6.ipv6mr_interface); err = setsockopt(*sktPtr, IPPROTO_IPV6, IPV6_JOIN_GROUP, &imr6, sizeof(imr6)); if (err < 0) { @@ -1025,7 +1036,7 @@ mDNSlocal int SetupOneInterface(mDNS *const m, struct sockaddr *intfAddr, struct // The interface is all ready to go, let's register it with the mDNS core. if (err == 0) - err = mDNS_RegisterInterface(m, &intf->coreIntf, 0); + err = mDNS_RegisterInterface(m, &intf->coreIntf, mDNSfalse); // Clean up. if (err == 0) diff --git a/mDNSPosix/mDNSPosix.h b/mDNSPosix/mDNSPosix.h index a5af557..f62d9c3 100755 --- a/mDNSPosix/mDNSPosix.h +++ b/mDNSPosix/mDNSPosix.h @@ -2,28 +2,24 @@ * * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: mDNSPosix.h,v $ +Revision 1.18 2006/08/14 23:24:47 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.17 2005/02/04 00:39:59 cheshire Move ParseDNSServers() from PosixDaemon.c to mDNSPosix.c so all Posix client layers can use it diff --git a/mDNSPosix/mDNSUNP.c b/mDNSPosix/mDNSUNP.c index f9bd4a6..ad1821c 100755 --- a/mDNSPosix/mDNSUNP.c +++ b/mDNSPosix/mDNSUNP.c @@ -2,28 +2,28 @@ * * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: mDNSUNP.c,v $ +Revision 1.34 2006/08/14 23:24:47 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + +Revision 1.33 2006/03/13 23:14:21 cheshire + Compile problems on FreeBSD +Use instead of + Revision 1.32 2005/12/21 02:56:43 cheshire get_ifi_info() should fake ifi_index when SIOCGIFINDEX undefined @@ -169,7 +169,9 @@ First checkin #endif #if defined(AF_INET6) && HAVE_IPV6 && !HAVE_LINUX -#include +#include +#include +// NOTE: netinet/in_var.h implicitly includes netinet6/in6_var.h for us #endif #if defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX @@ -186,8 +188,7 @@ void plen_to_mask(int plen, char *addr) { if(plen>bits_in_block) ones_in_block=bits_in_block; else ones_in_block=plen; block = ones & (ones << (bits_in_block-ones_in_block)); - i==0 ? sprintf(addr, "%x", block) : - sprintf(addr, "%s:%x", addr, block); + i==0 ? sprintf(addr, "%x", block) : sprintf(addr, "%s:%x", addr, block); plen -= ones_in_block; } } diff --git a/mDNSPosix/mDNSUNP.h b/mDNSPosix/mDNSUNP.h index 912c9d8..d0d75c4 100755 --- a/mDNSPosix/mDNSUNP.h +++ b/mDNSPosix/mDNSUNP.h @@ -2,28 +2,24 @@ * * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: mDNSUNP.h,v $ +Revision 1.19 2006/08/14 23:24:47 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.18 2005/04/08 21:37:57 ksekar get_ifi_info doesn't return IPv6 interfaces on Linux diff --git a/mDNSPosix/mdnsd.sh b/mDNSPosix/mdnsd.sh index ad06e01..d8b8ef4 100644 --- a/mDNSPosix/mdnsd.sh +++ b/mDNSPosix/mdnsd.sh @@ -1,28 +1,32 @@ #!/bin/sh +# Emacs settings: -*- tab-width: 4 -*- # -# Linux /etc/init.d script to start/stop the mdnsd daemon. -# Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. +# Copyright (c) 2002-2006 Apple Computer, Inc. All rights reserved. # -# @APPLE_LICENSE_HEADER_START@ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at # -# This file contains Original Code and/or Modifications of Original Code -# as defined in and that are subject to the Apple Public Source License -# Version 2.0 (the 'License'). You may not use this file except in -# compliance with the License. Please obtain a copy of the License at -# http://www.opensource.apple.com/apsl/ and read it before using this -# file. +# http://www.apache.org/licenses/LICENSE-2.0 # -# The Original Code and all software distributed under the License are -# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER -# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, -# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. -# Please see the License for the specific language governing rights and +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and # limitations under the License. -# -# @APPLE_LICENSE_HEADER_END@ +# +# Linux /etc/init.d script to start/stop the mdnsd daemon. # # $Log: mdnsd.sh,v $ +# Revision 1.9 2006/09/05 20:00:14 cheshire +# Moved Emacs settings to second line of file +# +# Revision 1.8 2006/08/29 16:42:01 mkrochma +# Fix POSIX startup script +# +# Revision 1.7 2006/08/14 23:24:47 cheshire +# Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 +# # Revision 1.6 2004/12/07 20:30:45 cheshire # Fix start-stop-daemon for Suse Linux (don't use -s TERM) # diff --git a/mDNSPosix/nss_mdns.c b/mDNSPosix/nss_mdns.c index 35e02fc..651a30d 100755 --- a/mDNSPosix/nss_mdns.c +++ b/mDNSPosix/nss_mdns.c @@ -155,7 +155,7 @@ format_reverse_addr_in ( /* Format an address structure as a string appropriate for DNS reverse (PTR) - lookup for AF_INET6. Output is in .ip6.int domain. + lookup for AF_INET6. Output is in .ip6.arpa domain. Parameters prefixlen @@ -491,22 +491,6 @@ const int MDNS_VERBOSE = 0; #define k_aliases_max 15 #define k_addrs_max 15 -const int k_mdnsd_intfs_local = 0; - // Tell mdnsd to perform lookups only using link-local interfaces. - /* - Currently, this feature is buggy. 0 will actually cause mdnsd to - do what it thinks is best. Unfortunately, this is to lookup 'local' - addresses locally and remote addresses via the DNS. Thus, lookups - for non-"local" addresses via mdns will not work correctly. - - Apple is currently modifying mdnsd to allow a special interface id - (expected value -2) to mean "always lookup locally". This constant - should be changed once the change is made. - - AW - 16 June 2004 - */ - - typedef struct buf_header { char hostname [k_hostname_maxlen + 1]; @@ -879,13 +863,13 @@ mdns_lookup_name ( switch (af) { case AF_INET: - rrtype = T_A; + rrtype = kDNSServiceType_A; result->hostent->h_length = 4; // Length of an A record break; case AF_INET6: - rrtype = T_AAAA; + rrtype = kDNSServiceType_AAAA; result->hostent->h_length = 16; // Length of an AAAA record break; @@ -902,11 +886,11 @@ mdns_lookup_name ( errcode = DNSServiceQueryRecord ( &sdref, - 0, // reserved flags field - k_mdnsd_intfs_local, // all local interfaces + kDNSServiceFlagsForceMulticast, // force multicast query + kDNSServiceInterfaceIndexAny, // all interfaces fullname, // full name to query for rrtype, // resource record type - C_IN, // internet class records + kDNSServiceClass_IN, // internet class records mdns_lookup_callback, // callback result // Context - result buffer ); @@ -977,11 +961,11 @@ mdns_lookup_addr ( errcode = DNSServiceQueryRecord ( &sdref, - 0, // reserved flags field - k_mdnsd_intfs_local, // all local interfaces + kDNSServiceFlagsForceMulticast, // force multicast query + kDNSServiceInterfaceIndexAny, // all interfaces addr_str, // address string to query for - T_PTR, // pointer RRs - C_IN, // internet class records + kDNSServiceType_PTR, // pointer RRs + kDNSServiceClass_IN, // internet class records mdns_lookup_callback, // callback result // Context - result buffer ); @@ -1121,7 +1105,7 @@ mdns_lookup_callback } // If a PTR - if (rrtype == T_PTR) + if (rrtype == kDNSServiceType_PTR) { if (callback_body_ptr (fullname, result, rdlen, rdata) < 0) return; @@ -1711,8 +1695,14 @@ const char * k_default_domains [] = { "local", "254.169.in-addr.arpa", - "0.8.e.f.ip6.int", - "0.8.e.f.ip6.arpa", + "8.e.f.ip6.int", + "8.e.f.ip6.arpa", + "9.e.f.ip6.int", + "9.e.f.ip6.arpa", + "a.e.f.ip6.int", + "a.e.f.ip6.arpa", + "b.e.f.ip6.int", + "b.e.f.ip6.arpa", NULL // Always null terminated }; @@ -2281,10 +2271,10 @@ rr_to_af (ns_type_t rrtype) { switch (rrtype) { - case T_A: + case kDNSServiceType_A: return AF_INET; - case T_AAAA: + case kDNSServiceType_AAAA: return AF_INET6; default: @@ -2299,10 +2289,10 @@ af_to_rr (int af) switch (af) { case AF_INET: - return T_A; + return kDNSServiceType_A; case AF_INET6: - return T_AAAA; + return kDNSServiceType_AAAA; default: //return ns_t_invalid; @@ -2423,9 +2413,9 @@ format_reverse_addr_in6 ( // divide prefixlen into nibbles, rounding up // Special handling for first - if (i / 2) + if (i % 2) { - curr += sprintf (curr, "%d.", (in_addr_a [i] >> 4) & 0x0F); + curr += sprintf (curr, "%d.", (in_addr_a [i/2] >> 4) & 0x0F); } i >>= 1; // Convert i to bytes (divide by 2) diff --git a/mDNSPosix/nss_mdns.conf b/mDNSPosix/nss_mdns.conf index 8f9b309..bdcdad7 100755 --- a/mDNSPosix/nss_mdns.conf +++ b/mDNSPosix/nss_mdns.conf @@ -2,6 +2,12 @@ # Applicable domains domain local -domain 0.8.e.f.ip6.int -domain 0.8.e.f.ip6.arpa domain 254.169.in-addr.arpa +domain 8.e.f.ip6.int +domain 9.e.f.ip6.int +domain a.e.f.ip6.int +domain b.e.f.ip6.int +domain 8.e.f.ip6.arpa +domain 9.e.f.ip6.arpa +domain a.e.f.ip6.arpa +domain b.e.f.ip6.arpa diff --git a/mDNSPosix/parselog.py b/mDNSPosix/parselog.py index ac14fc5..b58289f 100755 --- a/mDNSPosix/parselog.py +++ b/mDNSPosix/parselog.py @@ -1,29 +1,23 @@ #!/usr/bin/python - -# parselog.py, written and contributed by Kevin Marks +# Emacs settings: -*- tab-width: 4 -*- # # Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. # -# @APPLE_LICENSE_HEADER_START@ -# -# This file contains Original Code and/or Modifications of Original Code -# as defined in and that are subject to the Apple Public Source License -# Version 2.0 (the 'License'). You may not use this file except in -# compliance with the License. Please obtain a copy of the License at -# http://www.opensource.apple.com/apsl/ and read it before using this -# file. -# -# The Original Code and all software distributed under the License are -# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER -# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, -# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. -# Please see the License for the specific language governing rights and +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and # limitations under the License. # -# @APPLE_LICENSE_HEADER_END@ +# parselog.py, written and contributed by Kevin Marks # -# Requires OS X 10.3 Panther for Python and Core Graphics Python APIs +# Requires OS X 10.3 Panther or later, for Python and Core Graphics Python APIs # Invoke from the command line with "parselog.py fname" where fname is a log file made by mDNSNetMonitor # # Caveats: @@ -60,6 +54,12 @@ # Filled green circle: Normal answer Hollow green circle: Goodbye message (record going away) # Hollow blue circle: Legacy query (from old client) # $Log: parselog.py,v $ +# Revision 1.4 2006/09/05 20:00:14 cheshire +# Moved Emacs settings to second line of file +# +# Revision 1.3 2006/08/14 23:24:47 cheshire +# Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 +# # Revision 1.2 2003/12/01 21:47:44 cheshire # APSL # diff --git a/mDNSShared/CommonServices.h b/mDNSShared/CommonServices.h new file mode 100644 index 0000000..beaab56 --- /dev/null +++ b/mDNSShared/CommonServices.h @@ -0,0 +1,1504 @@ +/* -*- Mode: C; tab-width: 4 -*- + * + * Copyright (c) 1997-2004 Apple Computer, Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + + Change History (most recent first): + +$Log: CommonServices.h,v $ +Revision 1.3.4.1 2006/08/29 06:24:36 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + +Revision 1.3 2004/04/08 09:27:12 bradley +Added macro for portable specification of callback calling conventions. + +Revision 1.2 2004/03/07 05:53:39 bradley +Fixed NumVersion extraction macros. Updated error code mappings to match latest internal version. + +Revision 1.1 2004/01/30 02:25:59 bradley +Common Services and portability support for various platforms. + +*/ + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @header CommonServices + + Common Services for Mac OS X, Linux, Palm, VxWorks, Windows, and Windows CE. +*/ + +#ifndef __COMMON_SERVICES__ +#define __COMMON_SERVICES__ + +#ifdef __cplusplus + extern "C" { +#endif + +#if 0 +#pragma mark == Target == +#endif + +//=========================================================================================================================== +// Target +//=========================================================================================================================== + +// Macintosh + +#if( !defined( TARGET_OS_MAC ) ) + #if( ( macintosh || __MACH__ ) && !KERNEL ) + // ConditionalMacros.h in CoreServices will define this TARGET_* flag. + #else + #define TARGET_OS_MAC 0 + #endif +#endif + +#if( !defined( TARGET_API_MAC_OSX_KERNEL ) ) + #if( __MACH__ && KERNEL ) + #define TARGET_API_MAC_OSX_KERNEL 1 + #else + #define TARGET_API_MAC_OSX_KERNEL 0 + #endif +#endif + +// Linux + +#if( !defined( TARGET_OS_LINUX ) ) + #if( defined( __linux__ ) ) + #define TARGET_OS_LINUX 1 + #else + #define TARGET_OS_LINUX 0 + #endif +#endif + +// Palm + +#if( !defined( TARGET_OS_PALM ) ) + #if( defined( __PALMOS_TRAPS__ ) || defined( __PALMOS_ARMLET__ ) ) + #define TARGET_OS_PALM 1 + #else + #define TARGET_OS_PALM 0 + #endif +#endif + +// VxWorks + +#if( !defined( TARGET_OS_VXWORKS ) ) + + // No predefined macro for VxWorks so just assume VxWorks if nothing else is set. + + #if( !macintosh && !__MACH__ && !defined( __linux__ ) && !defined( __PALMOS_TRAPS__ ) && !defined( __PALMOS_ARMLET__ ) && !defined( _WIN32 ) ) + #define TARGET_OS_VXWORKS 1 + #else + #define TARGET_OS_VXWORKS 0 + #endif +#endif + +// Windows + +#if( !defined( TARGET_OS_WIN32 ) ) + #if( macintosh || __MACH__ ) + // ConditionalMacros.h in CoreServices will define this TARGET_* flag. + #else + #if( defined( _WIN32 ) ) + #define TARGET_OS_WIN32 1 + #else + #define TARGET_OS_WIN32 0 + #endif + #endif +#endif + +// Windows CE + +#if( !defined( TARGET_OS_WINDOWS_CE ) ) + #if( defined( _WIN32_WCE ) ) + #define TARGET_OS_WINDOWS_CE 1 + #else + #define TARGET_OS_WINDOWS_CE 0 + #endif +#endif + +#if 0 +#pragma mark == Includes == +#endif + +//=========================================================================================================================== +// Includes +//=========================================================================================================================== + +#if( !KERNEL ) + #include +#endif + +#if( ( macintosh || __MACH__ ) && !KERNEL ) + + #if( defined( __MWERKS__ ) ) + #if( __option( c9x ) ) + #include + #endif + #else + #include + #endif + + #include + + #if( __MACH__ ) + + // Mac OS X + + #include + #include + #include + #include + #include + #include + #include + #include + + #include + + #else + + // Classic Mac OS + + #include + #include + + #endif + +#elif( KERNEL ) + + // Mac OS X Kernel + + #include + + #include + #include + +#elif( TARGET_OS_LINUX ) + + // Linux (no special includes yet). + +#elif( TARGET_OS_PALM ) + + // Palm (no special includes yet). + +#elif( TARGET_OS_VXWORKS ) + + // VxWorks + + #include "vxWorks.h" + +#elif( TARGET_OS_WIN32 ) + + // Windows + + #if( !defined( WIN32_WINDOWS ) ) + #define WIN32_WINDOWS 0x0401 + #endif + + #if( !defined( _WIN32_WINDOWS ) ) + #define _WIN32_WINDOWS 0x0401 + #endif + + #if( !defined( WIN32_LEAN_AND_MEAN ) ) + #define WIN32_LEAN_AND_MEAN // Needed to avoid redefinitions by Windows interfaces. + #endif + + #if( defined( __MWERKS__ ) ) + + #if( __option( c9x ) ) + #include + #endif + + #include + + #elif( defined( _MSC_VER ) ) + + #pragma warning( disable:4127 ) // Disable "conditional expression is constant" warning for debug macros. + #pragma warning( disable:4706 ) // Disable "assignment within conditional expression" for Microsoft headers. + + #endif + + #include + #include + #include + + #if( defined( _MSC_VER ) ) + #pragma warning( default:4706 ) + #endif + +#else + #error unknown OS - update this file to support your OS +#endif + +#if( !defined( TARGET_BUILD_MAIN ) ) + #if( !TARGET_OS_VXWORKS ) + #define TARGET_BUILD_MAIN 1 + #endif +#endif + +#if( __GNUC__ || !TARGET_OS_VXWORKS ) + #define TARGET_LANGUAGE_C_LIKE 1 +#else + #define TARGET_LANGUAGE_C_LIKE 0 +#endif + +#if 0 +#pragma mark == CPU == +#endif + +//=========================================================================================================================== +// CPU +//=========================================================================================================================== + +// PowerPC + +#if( !defined( TARGET_CPU_PPC ) ) + #if( defined( __ppc__ ) || defined( __PPC__ ) || defined( powerpc ) || defined( ppc ) || defined( _M_MPPC ) ) + #define TARGET_CPU_PPC 1 + #else + #define TARGET_CPU_PPC 0 + #endif +#endif + +// x86 + +#if( !defined( TARGET_CPU_X86 ) ) + #if( __INTEL__ || defined( __i386__ ) || defined( i386 ) || defined( intel ) || defined( _M_IX86 ) ) + #define TARGET_CPU_X86 1 + #else + #define TARGET_CPU_X86 0 + #endif +#endif + +// MIPS + +#if( !defined( TARGET_CPU_MIPS ) ) + #if( __MIPS__ || defined( MIPS32 ) || defined( R3000 ) || defined( R4000 ) || defined( R4650 ) || defined( _M_MRX000 ) ) + #define TARGET_CPU_MIPS 1 + #else + #define TARGET_CPU_MIPS 0 + #endif +#endif + +#if( !defined( TARGET_CPU_PPC ) && !defined( TARGET_CPU_X86 ) && !defined( TARGET_CPU_MIPS ) ) + #error unknown CPU - update this file to support your CPU +#endif + +#if 0 +#pragma mark == Byte Order == +#endif + +//=========================================================================================================================== +// Byte Order +//=========================================================================================================================== + +// TARGET_RT_LITTLE_ENDIAN + +#if( !defined( TARGET_RT_LITTLE_ENDIAN ) ) + #if( MIPSEL || IL_LITTLE_ENDIAN || defined( __LITTLE_ENDIAN__ ) || \ + ( defined( BYTE_ORDER ) && defined( LITTLE_ENDIAN ) && ( BYTE_ORDER == LITTLE_ENDIAN ) ) || \ + ( defined( _BYTE_ORDER ) && defined( _LITTLE_ENDIAN ) && ( _BYTE_ORDER == _LITTLE_ENDIAN ) ) || \ + ( defined( __BYTE_ORDER ) && defined( __LITTLE_ENDIAN ) && ( __BYTE_ORDER == __LITTLE_ENDIAN ) ) || \ + TARGET_CPU_X86 || ( defined( TARGET_RT_BIG_ENDIAN ) && !TARGET_RT_BIG_ENDIAN ) ) + #define TARGET_RT_LITTLE_ENDIAN 1 + #else + #define TARGET_RT_LITTLE_ENDIAN 0 + #endif +#endif + +// TARGET_RT_BIG_ENDIAN + +#if( !defined( TARGET_RT_BIG_ENDIAN ) ) + #if( MIPSEB || IL_BIG_ENDIAN || defined( __BIG_ENDIAN__ ) || \ + ( defined( BYTE_ORDER ) && defined( BIG_ENDIAN ) && ( BYTE_ORDER == BIG_ENDIAN ) ) || \ + ( defined( _BYTE_ORDER ) && defined( _BIG_ENDIAN ) && ( _BYTE_ORDER == _BIG_ENDIAN ) ) || \ + ( defined( __BYTE_ORDER ) && defined( __BIG_ENDIAN ) && ( __BYTE_ORDER == __BIG_ENDIAN ) ) || \ + ( defined( TARGET_RT_LITTLE_ENDIAN ) && !TARGET_RT_LITTLE_ENDIAN ) ) + #define TARGET_RT_BIG_ENDIAN 1 + #else + #define TARGET_RT_BIG_ENDIAN 0 + #endif +#endif + +#if( defined( TARGET_RT_LITTLE_ENDIAN ) && !defined( TARGET_RT_BIG_ENDIAN ) ) + #if( TARGET_RT_LITTLE_ENDIAN ) + #define TARGET_RT_BIG_ENDIAN 0 + #else + #define TARGET_RT_BIG_ENDIAN 1 + #endif +#endif + +#if( defined( TARGET_RT_BIG_ENDIAN ) && !defined( TARGET_RT_LITTLE_ENDIAN ) ) + #if( TARGET_RT_BIG_ENDIAN ) + #define TARGET_RT_LITTLE_ENDIAN 0 + #else + #define TARGET_RT_LITTLE_ENDIAN 1 + #endif +#endif + +#if( !defined( TARGET_RT_LITTLE_ENDIAN ) || !defined( TARGET_RT_BIG_ENDIAN ) ) + #error unknown byte order - update this file to support your byte order +#endif + +// TARGET_RT_BYTE_ORDER + +#if( !defined( TARGET_RT_BYTE_ORDER_BIG_ENDIAN ) ) + #define TARGET_RT_BYTE_ORDER_BIG_ENDIAN 1234 +#endif + +#if( !defined( TARGET_RT_BYTE_ORDER_LITTLE_ENDIAN ) ) + #define TARGET_RT_BYTE_ORDER_LITTLE_ENDIAN 4321 +#endif + +#if( !defined( TARGET_RT_BYTE_ORDER ) ) + #if( TARGET_RT_LITTLE_ENDIAN ) + #define TARGET_RT_BYTE_ORDER TARGET_RT_BYTE_ORDER_LITTLE_ENDIAN + #else + #define TARGET_RT_BYTE_ORDER TARGET_RT_BYTE_ORDER_BIG_ENDIAN + #endif +#endif + +#if 0 +#pragma mark == Constants == +#endif + +//=========================================================================================================================== +// Constants +//=========================================================================================================================== + +#if( !TARGET_OS_MAC ) + #define CR '\r' +#endif + +#define LF '\n' +#define CRSTR "\r" +#define LFSTR "\n" +#define CRLF "\r\n" +#define CRCR "\r\r" + +#if 0 +#pragma mark == Compatibility == +#endif + +//=========================================================================================================================== +// Compatibility +//=========================================================================================================================== + +// Macros to allow the same code to work on Windows and other sockets API-compatible platforms. + +#if( TARGET_OS_WIN32 ) + #define close_compat( X ) closesocket( X ) + #define errno_compat() (int) GetLastError() + #define set_errno_compat( X ) SetLastError( X ) + #define EWOULDBLOCK_compat WSAEWOULDBLOCK + #define ETIMEDOUT_compat WSAETIMEDOUT + #define ENOTCONN_compat WSAENOTCONN + #define IsValidSocket( X ) ( ( X ) != INVALID_SOCKET ) + #define kInvalidSocketRef INVALID_SOCKET + #if( TARGET_LANGUAGE_C_LIKE ) + typedef SOCKET SocketRef; + #endif +#else + #define close_compat( X ) close( X ) + #define errno_compat() errno + #define set_errno_compat( X ) do { errno = ( X ); } while( 0 ) + #define EWOULDBLOCK_compat EWOULDBLOCK + #define ETIMEDOUT_compat ETIMEDOUT + #define ENOTCONN_compat ENOTCONN + #define IsValidSocket( X ) ( ( X ) >= 0 ) + #define kInvalidSocketRef -1 + #if( TARGET_LANGUAGE_C_LIKE ) + typedef int SocketRef; + #endif +#endif + +// socklen_t is not defined on the following platforms so emulate it if not defined: +// +// - Pre-Panther Mac OS X. Panther defines SO_NOADDRERR so trigger off that. +// - Windows SDK prior to 2003. 2003+ SDK's define EAI_AGAIN so trigger off that. +// - VxWorks + +#if( TARGET_LANGUAGE_C_LIKE ) + #if( ( TARGET_OS_MAC && !defined( SO_NOADDRERR ) ) || ( TARGET_OS_WIN32 && !defined( EAI_AGAIN ) ) || TARGET_OS_VXWORKS ) + typedef int socklen_t; + #endif +#endif + +// ssize_t is not defined on the following platforms so emulate it if not defined: +// +// - Mac OS X when not building with BSD headers +// - Windows + +#if( TARGET_LANGUAGE_C_LIKE ) + #if( ( TARGET_OS_WIN32 || !defined( _BSD_SSIZE_T_DEFINED_ ) ) && !TARGET_OS_VXWORKS ) + typedef int ssize_t; + #endif +#endif + +// sockaddr_storage is not supported on non-IPv6 machines so alias it to an IPv4-compatible structure. + +#if( TARGET_LANGUAGE_C_LIKE ) + #if( !defined( AF_INET6 ) ) + #define sockaddr_storage sockaddr_in + #define ss_family sin_family + #endif +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined SOCKADDR_IS_IP_LOOPBACK + + @abstract Determines if a sockaddr is an IPv4 or IPv6 loopback address (if IPv6 is supported). +*/ + +#if( defined( AF_INET6 ) ) + #define SOCKADDR_IS_IP_LOOPBACK( SA ) \ + ( ( (const struct sockaddr *)( SA ) )->sa_family == AF_INET ) \ + ? ( ( (const struct sockaddr_in *)( SA ) )->sin_addr.s_addr == htonl( INADDR_LOOPBACK ) ) \ + : ( ( (const struct sockaddr *)( SA ) )->sa_family == AF_INET6 ) \ + ? IN6_IS_ADDR_LOOPBACK( &( (const struct sockaddr_in6 *)( SA ) )->sin6_addr ) \ + : 0 +#else + #define SOCKADDR_IS_IP_LOOPBACK( SA ) \ + ( ( (const struct sockaddr *)( SA ) )->sa_family == AF_INET ) \ + ? ( ( (const struct sockaddr_in *)( SA ) )->sin_addr.s_addr == htonl( INADDR_LOOPBACK ) ) \ + : 0 +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined SOCKADDR_IS_IP_LINK_LOCAL + + @abstract Determines if a sockaddr is an IPv4 or IPv6 link-local address (if IPv6 is supported). +*/ + +#if( defined( AF_INET6 ) ) + #define SOCKADDR_IS_IP_LINK_LOCAL( SA ) \ + ( ( ( (const struct sockaddr *)( SA ) )->sa_family == AF_INET ) \ + ? ( ( ( (uint8_t *)( &( (const struct sockaddr_in *)( SA ) )->sin_addr ) )[ 0 ] == 169 ) && \ + ( ( (uint8_t *)( &( (const struct sockaddr_in *)( SA ) )->sin_addr ) )[ 1 ] == 254 ) ) \ + : IN6_IS_ADDR_LOOPBACK( &( (const struct sockaddr_in6 *)( SA ) )->sin6_addr ) ) +#else + #define SOCKADDR_IS_IP_LINK_LOCAL( SA ) \ + ( ( ( (const struct sockaddr *)( SA ) )->sa_family == AF_INET ) \ + ? ( ( ( (uint8_t *)( &( (const struct sockaddr_in *)( SA ) )->sin_addr ) )[ 0 ] == 169 ) && \ + ( ( (uint8_t *)( &( (const struct sockaddr_in *)( SA ) )->sin_addr ) )[ 1 ] == 254 ) ) \ + : 0 ) +#endif + +// _beginthreadex and _endthreadex are not supported on Windows CE 2.1 or later (the C runtime issues with leaking +// resources have apparently been resolved and they seem to have just ripped out support for the API) so map it to +// CreateThread on Windows CE. + +#if( TARGET_OS_WINDOWS_CE ) + #define _beginthreadex_compat( SECURITY_PTR, STACK_SIZE, START_ADDRESS, ARG_LIST, FLAGS, THREAD_ID_PTR ) \ + (uintptr_t) CreateThread( SECURITY_PTR, STACK_SIZE, (LPTHREAD_START_ROUTINE) START_ADDRESS, ARG_LIST, FLAGS, \ + (LPDWORD) THREAD_ID_PTR ) + + #define _endthreadex_compat( RESULT ) ExitThread( (DWORD) RESULT ) +#elif( TARGET_OS_WIN32 ) + #define _beginthreadex_compat _beginthreadex + #define _endthreadex_compat _endthreadex +#endif + +// The C99 "inline" keyword is not supported by Microsoft compilers, but they do support __inline so map it when needed. + +#if( defined( _MSC_VER ) ) + #define inline_compat __inline +#else + #define inline_compat inline +#endif + +// Calling conventions + +#if( !defined( CALLBACK_COMPAT ) ) + #if( TARGET_OS_WIN32 || TARGET_OS_WINDOWS_CE ) + #define CALLBACK_COMPAT CALLBACK + #else + #define CALLBACK_COMPAT + #endif +#endif + +#if 0 +#pragma mark == Macros == +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined kSizeCString + + @abstract A meta-value to pass to supported routines to indicate the size should be calculated with strlen. +*/ + +#define kSizeCString ( (size_t) -1 ) + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined sizeof_array + + @abstract Determines the number of elements in an array. +*/ + +#define sizeof_array( X ) ( sizeof( X ) / sizeof( X[ 0 ] ) ) + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined sizeof_element + + @abstract Determines the size of an array element. +*/ + +#define sizeof_element( X ) sizeof( X[ 0 ] ) + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined sizeof_string + + @abstract Determines the size of a constant C string, excluding the null terminator. +*/ + +#define sizeof_string( X ) ( sizeof( ( X ) ) - 1 ) + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined sizeof_field + + @abstract Determines the size of a field of a type. +*/ + +#define sizeof_field( TYPE, FIELD ) sizeof( ( ( (TYPE *) 0 )->FIELD ) ) + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @function RoundUp + + @abstract Rounds X up to a multiple of Y. +*/ + +#define RoundUp( X, Y ) ( ( X ) + ( ( Y ) - ( ( X ) % ( Y ) ) ) ) + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @function IsAligned + + @abstract Returns non-zero if X is aligned to a Y byte boundary and 0 if not. Y must be a power of 2. +*/ + +#define IsAligned( X, Y ) ( ( ( X ) & ( ( Y ) - 1 ) ) == 0 ) + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @function IsFieldAligned + + @abstract Returns non-zero if FIELD of type TYPE is aligned to a Y byte boundary and 0 if not. Y must be a power of 2. +*/ + +#define IsFieldAligned( X, TYPE, FIELD, Y ) IsAligned( ( (uintptr_t)( X ) ) + offsetof( TYPE, FIELD ), ( Y ) ) + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @function AlignDown + + @abstract Aligns X down to a Y byte boundary. Y must be a power of 2. +*/ + +#define AlignDown( X, Y ) ( ( X ) & ~( ( Y ) - 1 ) ) + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @function AlignUp + + @abstract Aligns X up to a Y byte boundary. Y must be a power of 2. +*/ + +#define AlignUp( X, Y ) ( ( ( X ) + ( ( Y ) - 1 ) ) & ~( ( Y ) - 1 ) ) + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @function Min + + @abstract Returns the lesser of X and Y. +*/ + +#if( !defined( Min ) ) + #define Min( X, Y ) ( ( ( X ) < ( Y ) ) ? ( X ) : ( Y ) ) +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @function Max + + @abstract Returns the greater of X and Y. +*/ + +#if( !defined( Max ) ) + #define Max( X, Y ) ( ( ( X ) > ( Y ) ) ? ( X ) : ( Y ) ) +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @function InsertBits + + @abstract Inserts BITS (both 0 and 1 bits) into X, controlled by MASK and SHIFT, and returns the result. + + @discussion + + MASK is the bitmask of the bits in the final position. + SHIFT is the number of bits to shift left for 1 to reach the first bit position of MASK. + + For example, if you wanted to insert 0x3 into the leftmost 4 bits of a 32-bit value: + + InsertBits( 0, 0x3, 0xF0000000U, 28 ) == 0x30000000 +*/ + +#define InsertBits( X, BITS, MASK, SHIFT ) ( ( ( X ) & ~( MASK ) ) | ( ( ( BITS ) << ( SHIFT ) ) & ( MASK ) ) ) + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @function ExtractBits + + @abstract Extracts bits from X, controlled by MASK and SHIFT, and returns the result. + + @discussion + + MASK is the bitmask of the bits in the final position. + SHIFT is the number of bits to shift right to right justify MASK. + + For example, if you had a 32-bit value (e.g. 0x30000000) wanted the left-most 4 bits (e.g. 3 in this example): + + ExtractBits( 0x30000000U, 0xF0000000U, 28 ) == 0x3 +*/ + +#define ExtractBits( X, MASK, SHIFT ) ( ( ( X ) >> ( SHIFT ) ) & ( ( MASK ) >> ( SHIFT ) ) ) + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @function Stringify + + @abstract Stringify's an expression. + + @discussion + + Stringify macros to process raw text passed via -D options to C string constants. The double-wrapping is necessary + because the C preprocessor doesn't perform its normal argument expansion pre-scan with stringified macros so the + -D macro needs to be expanded once via the wrapper macro then stringified so the raw text is stringified. Otherwise, + the replacement value would be used instead of the symbolic name (only for preprocessor symbols like #defines). + + For example: + + #define kMyConstant 1 + + printf( "%s", Stringify( kMyConstant ) ); // Prints "kMyConstant" + printf( "%s", StringifyExpansion( kMyConstant ) ); // Prints "1" + + Non-preprocessor symbols do not have this issue. For example: + + enum + { + kMyConstant = 1 + }; + + printf( "%s", Stringify( kMyConstant ) ); // Prints "kMyConstant" + printf( "%s", StringifyExpansion( kMyConstant ) ); // Prints "kMyConstant" + + See for more info on C preprocessor pre-scanning. +*/ + +#define Stringify( X ) # X +#define StringifyExpansion( X ) Stringify( X ) + +#if 0 +#pragma mark == Types == +#endif + +#if( TARGET_LANGUAGE_C_LIKE ) +//=========================================================================================================================== +// Standard Types +//=========================================================================================================================== + +#if( !defined( INT8_MIN ) ) + + #define INT8_MIN SCHAR_MIN + + #if( defined( _MSC_VER ) ) + + // C99 stdint.h not supported in VC++/VS.NET yet. + + typedef INT8 int8_t; + typedef UINT8 uint8_t; + typedef INT16 int16_t; + typedef UINT16 uint16_t; + typedef INT32 int32_t; + typedef UINT32 uint32_t; + typedef __int64 int64_t; + typedef unsigned __int64 uint64_t; + + #elif( TARGET_OS_VXWORKS && ( TORNADO_VERSION < 220 ) ) + typedef long long int64_t; + typedef unsigned long long uint64_t; + #endif + + typedef int8_t int_least8_t; + typedef int16_t int_least16_t; + typedef int32_t int_least32_t; + typedef int64_t int_least64_t; + + typedef uint8_t uint_least8_t; + typedef uint16_t uint_least16_t; + typedef uint32_t uint_least32_t; + typedef uint64_t uint_least64_t; + + typedef int8_t int_fast8_t; + typedef int16_t int_fast16_t; + typedef int32_t int_fast32_t; + typedef int64_t int_fast64_t; + + typedef uint8_t uint_fast8_t; + typedef uint16_t uint_fast16_t; + typedef uint32_t uint_fast32_t; + typedef uint64_t uint_fast64_t; + + #if( !defined( _MSC_VER ) || TARGET_OS_WINDOWS_CE ) + typedef long int intptr_t; + typedef unsigned long int uintptr_t; + #endif + +#endif + +// Macros for minimum-width integer constants + +#if( !defined( INT8_C ) ) + #define INT8_C( value ) value +#endif + +#if( !defined( INT16_C ) ) + #define INT16_C( value ) value +#endif + +#if( !defined( INT32_C ) ) + #define INT32_C( value ) value ## L +#endif + +#if( !defined( INT64_C ) ) + #if( defined( _MSC_VER ) ) + #define INT64_C( value ) value ## i64 + #else + #define INT64_C( value ) value ## LL + #endif +#endif + +#if( !defined( UINT8_C ) ) + #define UINT8_C( value ) value ## U +#endif + +#if( !defined( UINT16_C ) ) + #define UINT16_C( value ) value ## U +#endif + +#if( !defined( UINT32_C ) ) + #define UINT32_C( value ) value ## UL +#endif + +#if( !defined( UINT64_C ) ) + #if( defined( _MSC_VER ) ) + #define UINT64_C( value ) value ## UI64 + #else + #define UINT64_C( value ) value ## ULL + #endif +#endif + +#if 0 +#pragma mark == bool == +#endif + +//=========================================================================================================================== +// Boolean Constants and Types +//=========================================================================================================================== + +// C++ defines bool, true, and false. Metrowerks allows this to be controlled by the "bool" option though. +// C99 defines __bool_true_false_are_defined when bool, true, and false are defined. +// MacTypes.h defines true and false (Mac builds only). +// +// Note: The Metrowerks has to be in its own block because Microsoft Visual Studio .NET does not completely +// short-circuit and gets confused by the option( bool ) portion of the conditional. + +#if( defined( __MWERKS__ ) ) + + // Note: The following test is done on separate lines because CodeWarrior doesn't like it all on one line. + + #if( !__bool_true_false_are_defined && ( !defined( __cplusplus ) || !__option( bool ) ) ) + #define COMMON_SERVICES_NEEDS_BOOL 1 + #else + #define COMMON_SERVICES_NEEDS_BOOL 0 + #endif + + // Workaround when building with CodeWarrior, but using the Apple stdbool.h header, which uses _Bool. + + #if( __bool_true_false_are_defined && !defined( __cplusplus ) && !__option( c9x ) ) + #define _Bool int + #endif + + // Workaround when building with CodeWarrior for C++ with bool disabled and using the Apple stdbool.h header, + // which defines true and false to map to C++ true and false (which are not enabled). Serenity Now! + + #if( __bool_true_false_are_defined && defined( __cplusplus ) && !__option( bool ) ) + #define true 1 + #define false 0 + #endif +#else + #define COMMON_SERVICES_NEEDS_BOOL ( !defined( __cplusplus ) && !__bool_true_false_are_defined ) +#endif + +#if( COMMON_SERVICES_NEEDS_BOOL ) + + typedef int bool; + + #define bool bool + + #if( !defined( __MACTYPES__ ) && !defined( true ) && !defined( false ) ) + #define true 1 + #define false 0 + #endif + + #define __bool_true_false_are_defined 1 +#endif + +// IOKit IOTypes.h typedef's bool if TYPE_BOOL is not defined so define it here to prevent redefinition by IOTypes.h. + +#if( TARGET_API_MAC_OSX_KERNEL ) + #define TYPE_BOOL 1 +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @typedef CStr255 + + @abstract 255 character null-terminated (C-style) string. +*/ + +#if( TARGET_LANGUAGE_C_LIKE ) + typedef char CStr255[ 256 ]; +#endif + +#endif // TARGET_LANGUAGE_C_LIKE + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined TYPE_LONGLONG_NATIVE + + @abstract Defines whether long long (or its equivalent) is natively supported or requires special libraries. +*/ + +#if( !defined( TYPE_LONGLONG_NATIVE ) ) + #if( !TARGET_OS_VXWORKS ) + #define TYPE_LONGLONG_NATIVE 1 + #else + #define TYPE_LONGLONG_NATIVE 0 + #endif +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined long_long_compat + + @abstract Compatibility type to map to the closest thing to long long and unsigned long long. + + @discussion + + Neither long long nor unsigned long long are supported by Microsoft compilers, but they do support proprietary + "__int64" and "unsigned __int64" equivalents so map to those types if the real long long is not supported. +*/ + +#if( TARGET_LANGUAGE_C_LIKE ) + #if( TARGET_OS_WIN32 ) + typedef __int64 long_long_compat; + typedef unsigned __int64 unsigned_long_long_compat; + #else + typedef signed long long long_long_compat; + typedef unsigned long long unsigned_long_long_compat; + #endif +#endif + +#if 0 +#pragma mark == Errors == +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @enum OSStatus + + @abstract Status Code + + @constant kNoErr 0 No error occurred. + @constant kInProgressErr 1 Operation in progress. + @constant kUnknownErr -6700 Unknown error occurred. + @constant kOptionErr -6701 Option was not acceptable. + @constant kSelectorErr -6702 Selector passed in is invalid or unknown. + @constant kExecutionStateErr -6703 Call made in the wrong execution state (e.g. called at interrupt time). + @constant kPathErr -6704 Path is invalid, too long, or otherwise not usable. + @constant kParamErr -6705 Parameter is incorrect, missing, or not appropriate. + @constant kParamCountErr -6706 Incorrect or unsupported number of parameters. + @constant kCommandErr -6707 Command invalid or not supported. + @constant kIDErr -6708 Unknown, invalid, or inappropriate identifier. + @constant kStateErr -6709 Not in appropriate state to perform operation. + @constant kRangeErr -6710 Index is out of range or not valid. + @constant kRequestErr -6711 Request was improperly formed or not appropriate. + @constant kResponseErr -6712 Response was incorrect or out of sequence. + @constant kChecksumErr -6713 Checksum does not match the actual data. + @constant kNotHandledErr -6714 Operation was not handled (or not handled completely). + @constant kVersionErr -6715 Version is not incorrect or not compatibile. + @constant kSignatureErr -6716 Signature did not match what was expected. + @constant kFormatErr -6717 Unknown, invalid, or inappropriate file/data format. + @constant kNotInitializedErr -6718 Action request before needed services were initialized. + @constant kAlreadyInitializedErr -6719 Attempt made to initialize when already initialized. + @constant kNotInUseErr -6720 Object not in use (e.g. cannot abort if not already in use). + @constant kInUseErr -6721 Object is in use (e.g. cannot reuse active param blocks). + @constant kTimeoutErr -6722 Timeout occurred. + @constant kCanceledErr -6723 Operation canceled (successful cancel). + @constant kAlreadyCanceledErr -6724 Operation has already been canceled. + @constant kCannotCancelErr -6725 Operation could not be canceled (maybe already done or invalid). + @constant kDeletedErr -6726 Object has already been deleted. + @constant kNotFoundErr -6727 Something was not found. + @constant kNoMemoryErr -6728 Not enough memory was available to perform the operation. + @constant kNoResourcesErr -6729 Resources unavailable to perform the operation. + @constant kDuplicateErr -6730 Duplicate found or something is a duplicate. + @constant kImmutableErr -6731 Entity is not changeable. + @constant kUnsupportedDataErr -6732 Data is unknown or not supported. + @constant kIntegrityErr -6733 Data is corrupt. + @constant kIncompatibleErr -6734 Data is not compatible or it is in an incompatible format. + @constant kUnsupportedErr -6735 Feature or option is not supported. + @constant kUnexpectedErr -6736 Error occurred that was not expected. + @constant kValueErr -6737 Value is not appropriate. + @constant kNotReadableErr -6738 Could not read or reading is not allowed. + @constant kNotWritableErr -6739 Could not write or writing is not allowed. + @constant kBadReferenceErr -6740 An invalid or inappropriate reference was specified. + @constant kFlagErr -6741 An invalid, inappropriate, or unsupported flag was specified. + @constant kMalformedErr -6742 Something was not formed correctly. + @constant kSizeErr -6743 Size was too big, too small, or not appropriate. + @constant kNameErr -6744 Name was not correct, allowed, or appropriate. + @constant kNotReadyErr -6745 Device or service is not ready. + @constant kReadErr -6746 Could not read. + @constant kWriteErr -6747 Could not write. + @constant kMismatchErr -6748 Something does not match. + @constant kDateErr -6749 Date is invalid or out-of-range. + @constant kUnderrunErr -6750 Less data than expected. + @constant kOverrunErr -6751 More data than expected. + @constant kEndingErr -6752 Connection, session, or something is ending. + @constant kConnectionErr -6753 Connection failed or could not be established. + @constant kAuthenticationErr -6754 Authentication failed or is not supported. + @constant kOpenErr -6755 Could not open file, pipe, device, etc. + @constant kTypeErr -6756 Incorrect or incompatible type (e.g. file, data, etc.). + @constant kSkipErr -6757 Items should be or was skipped. + @constant kNoAckErr -6758 No acknowledge. + @constant kCollisionErr -6759 Collision occurred (e.g. two on bus at same time). + @constant kBackoffErr -6760 Backoff in progress and operation intentionally failed. + @constant kNoAddressAckErr -6761 No acknowledge of address. + @constant kBusyErr -6762 Cannot perform because something is busy. + @constant kNoSpaceErr -6763 Not enough space to perform operation. +*/ + +#if( TARGET_LANGUAGE_C_LIKE ) + #if( !TARGET_OS_MAC && !TARGET_API_MAC_OSX_KERNEL ) + typedef int32_t OSStatus; + #endif +#endif + +#define kNoErr 0 +#define kInProgressErr 1 + +// Generic error codes are in the range -6700 to -6779. + +#define kGenericErrorBase -6700 // Starting error code for all generic errors. + +#define kUnknownErr -6700 +#define kOptionErr -6701 +#define kSelectorErr -6702 +#define kExecutionStateErr -6703 +#define kPathErr -6704 +#define kParamErr -6705 +#define kParamCountErr -6706 +#define kCommandErr -6707 +#define kIDErr -6708 +#define kStateErr -6709 +#define kRangeErr -6710 +#define kRequestErr -6711 +#define kResponseErr -6712 +#define kChecksumErr -6713 +#define kNotHandledErr -6714 +#define kVersionErr -6715 +#define kSignatureErr -6716 +#define kFormatErr -6717 +#define kNotInitializedErr -6718 +#define kAlreadyInitializedErr -6719 +#define kNotInUseErr -6720 +#define kInUseErr -6721 +#define kTimeoutErr -6722 +#define kCanceledErr -6723 +#define kAlreadyCanceledErr -6724 +#define kCannotCancelErr -6725 +#define kDeletedErr -6726 +#define kNotFoundErr -6727 +#define kNoMemoryErr -6728 +#define kNoResourcesErr -6729 +#define kDuplicateErr -6730 +#define kImmutableErr -6731 +#define kUnsupportedDataErr -6732 +#define kIntegrityErr -6733 +#define kIncompatibleErr -6734 +#define kUnsupportedErr -6735 +#define kUnexpectedErr -6736 +#define kValueErr -6737 +#define kNotReadableErr -6738 +#define kNotWritableErr -6739 +#define kBadReferenceErr -6740 +#define kFlagErr -6741 +#define kMalformedErr -6742 +#define kSizeErr -6743 +#define kNameErr -6744 +#define kNotReadyErr -6745 +#define kReadErr -6746 +#define kWriteErr -6747 +#define kMismatchErr -6748 +#define kDateErr -6749 +#define kUnderrunErr -6750 +#define kOverrunErr -6751 +#define kEndingErr -6752 +#define kConnectionErr -6753 +#define kAuthenticationErr -6754 +#define kOpenErr -6755 +#define kTypeErr -6756 +#define kSkipErr -6757 +#define kNoAckErr -6758 +#define kCollisionErr -6759 +#define kBackoffErr -6760 +#define kNoAddressAckErr -6761 +#define kBusyErr -6762 +#define kNoSpaceErr -6763 + +#define kGenericErrorEnd -6779 // Last generic error code (inclusive) + +#if 0 +#pragma mark == Mac Compatibility == +#endif + +//=========================================================================================================================== +// Mac Compatibility +//=========================================================================================================================== + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @enum Duration + + @abstract Type used to specify a duration of time. + + @constant kDurationImmediate Indicates no delay/wait time. + @constant kDurationMicrosecond Microsecond units. + @constant kDurationMillisecond Millisecond units. + @constant kDurationSecond Second units. + @constant kDurationMinute Minute units. + @constant kDurationHour Hour units. + @constant kDurationDay Day units. + @constant kDurationForever Infinite period of time (no timeout). + + @discussion + + Duration values are intended to be multiplied by the specific interval to achieve an actual duration. For example, + to wait for 5 seconds you would use "5 * kDurationSecond". +*/ + +#if( TARGET_LANGUAGE_C_LIKE ) + #if( !TARGET_OS_MAC ) + typedef int32_t Duration; + #endif +#endif + +#define kDurationImmediate 0L +#define kDurationMicrosecond -1L +#define kDurationMillisecond 1L +#define kDurationSecond ( 1000L * kDurationMillisecond ) +#define kDurationMinute ( 60L * kDurationSecond ) +#define kDurationHour ( 60L * kDurationMinute ) +#define kDurationDay ( 24L * kDurationHour ) +#define kDurationForever 0x7FFFFFFFL + +// Seconds <-> Minutes <-> Hours <-> Days <-> Weeks <-> Months <-> Years conversions + +#define kNanosecondsPerMicrosecond 1000 +#define kNanosecondsPerMillisecond 1000000 +#define kNanosecondsPerSecond 1000000000 +#define kMicrosecondsPerSecond 1000000 +#define kMicrosecondsPerMillisecond 1000 +#define kMillisecondsPerSecond 1000 +#define kSecondsPerMinute 60 +#define kSecondsPerHour ( 60 * 60 ) // 3600 +#define kSecondsPerDay ( 60 * 60 * 24 ) // 86400 +#define kSecondsPerWeek ( 60 * 60 * 24 * 7 ) // 604800 +#define kMinutesPerHour 60 +#define kMinutesPerDay ( 60 * 24 ) // 1440 +#define kHoursPerDay 24 +#define kDaysPerWeek 7 +#define kWeeksPerYear 52 +#define kMonthsPerYear 12 + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined VersionStages + + @abstract NumVersion-style version stages. +*/ + +#define kVersionStageDevelopment 0x20 +#define kVersionStageAlpha 0x40 +#define kVersionStageBeta 0x60 +#define kVersionStageFinal 0x80 + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @function NumVersionBuild + + @abstract Builds a 32-bit Mac-style NumVersion value (e.g. NumVersionBuild( 1, 2, 3, kVersionStageBeta, 4 ) -> 1.2.3b4). +*/ + +#define NumVersionBuild( MAJOR, MINOR, BUGFIX, STAGE, REV ) \ + ( ( ( ( MAJOR ) & 0xFF ) << 24 ) | \ + ( ( ( MINOR ) & 0x0F ) << 20 ) | \ + ( ( ( BUGFIX ) & 0x0F ) << 16 ) | \ + ( ( ( STAGE ) & 0xFF ) << 8 ) | \ + ( ( ( REV ) & 0xFF ) ) ) + +#define NumVersionExtractMajor( VERSION ) ( (uint8_t)( ( ( VERSION ) >> 24 ) & 0xFF ) ) +#define NumVersionExtractMinorAndBugFix( VERSION ) ( (uint8_t)( ( ( VERSION ) >> 16 ) & 0xFF ) ) +#define NumVersionExtractMinor( VERSION ) ( (uint8_t)( ( ( VERSION ) >> 20 ) & 0x0F ) ) +#define NumVersionExtractBugFix( VERSION ) ( (uint8_t)( ( ( VERSION ) >> 16 ) & 0x0F ) ) +#define NumVersionExtractStage( VERSION ) ( (uint8_t)( ( ( VERSION ) >> 8 ) & 0xFF ) ) +#define NumVersionExtractRevision( VERSION ) ( (uint8_t)( ( VERSION ) & 0xFF ) ) + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @function NumVersionCompare + + @abstract Compares two NumVersion values and returns the following values: + + left < right -> -1 + left > right -> 1 + left = right -> 0 +*/ + +#if( TARGET_LANGUAGE_C_LIKE ) + int NumVersionCompare( uint32_t inLeft, uint32_t inRight ); +#endif + +#if 0 +#pragma mark == Binary Constants == +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined binary_4 + + @abstract Macro to generate an 4-bit constant using binary notation (e.g. binary_4( 1010 ) == 0xA). +*/ + +#define binary_4( a ) binary_4_hex_wrap( hex_digit4( a ) ) +#define binary_4_hex_wrap( a ) binary_4_hex( a ) +#define binary_4_hex( a ) ( 0x ## a ) + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined binary_8 + + @abstract Macro to generate an 8-bit constant using binary notation (e.g. binary_8( 01111011 ) == 0x7B). +*/ + +#define binary_8( a ) binary_8_hex_wrap( hex_digit8( a ) ) +#define binary_8_hex_wrap( a ) binary_8_hex( a ) +#define binary_8_hex( a ) ( 0x ## a ) + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined binary_16 + + @abstract Macro to generate an 16-bit constant using binary notation (e.g. binary_16( 01111011, 01111011 ) == 0x7B7B). +*/ + +#define binary_16( a, b ) binary_16_hex_wrap( hex_digit8( a ), hex_digit8( b ) ) +#define binary_16_hex_wrap( a, b ) binary_16_hex( a, b ) +#define binary_16_hex( a, b ) ( 0x ## a ## b ) + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined binary_32 + + @abstract Macro to generate an 32-bit constant using binary notation + (e.g. binary_32( 01111011, 01111011, 01111011, 01111011 ) == 0x7B7B7B7B). +*/ + +#define binary_32( a, b, c, d ) binary_32_hex_wrap( hex_digit8( a ), hex_digit8( b ), hex_digit8( c ), hex_digit8( d ) ) +#define binary_32_hex_wrap( a, b, c, d ) binary_32_hex( a, b, c, d ) +#define binary_32_hex( a, b, c, d ) ( 0x ## a ## b ## c ## d ) + +// Binary Constant Helpers + +#define hex_digit8( a ) HEX_DIGIT_ ## a +#define hex_digit4( a ) HEX_DIGIT_ ## 0000 ## a + +#define HEX_DIGIT_00000000 00 +#define HEX_DIGIT_00000001 01 +#define HEX_DIGIT_00000010 02 +#define HEX_DIGIT_00000011 03 +#define HEX_DIGIT_00000100 04 +#define HEX_DIGIT_00000101 05 +#define HEX_DIGIT_00000110 06 +#define HEX_DIGIT_00000111 07 +#define HEX_DIGIT_00001000 08 +#define HEX_DIGIT_00001001 09 +#define HEX_DIGIT_00001010 0A +#define HEX_DIGIT_00001011 0B +#define HEX_DIGIT_00001100 0C +#define HEX_DIGIT_00001101 0D +#define HEX_DIGIT_00001110 0E +#define HEX_DIGIT_00001111 0F +#define HEX_DIGIT_00010000 10 +#define HEX_DIGIT_00010001 11 +#define HEX_DIGIT_00010010 12 +#define HEX_DIGIT_00010011 13 +#define HEX_DIGIT_00010100 14 +#define HEX_DIGIT_00010101 15 +#define HEX_DIGIT_00010110 16 +#define HEX_DIGIT_00010111 17 +#define HEX_DIGIT_00011000 18 +#define HEX_DIGIT_00011001 19 +#define HEX_DIGIT_00011010 1A +#define HEX_DIGIT_00011011 1B +#define HEX_DIGIT_00011100 1C +#define HEX_DIGIT_00011101 1D +#define HEX_DIGIT_00011110 1E +#define HEX_DIGIT_00011111 1F +#define HEX_DIGIT_00100000 20 +#define HEX_DIGIT_00100001 21 +#define HEX_DIGIT_00100010 22 +#define HEX_DIGIT_00100011 23 +#define HEX_DIGIT_00100100 24 +#define HEX_DIGIT_00100101 25 +#define HEX_DIGIT_00100110 26 +#define HEX_DIGIT_00100111 27 +#define HEX_DIGIT_00101000 28 +#define HEX_DIGIT_00101001 29 +#define HEX_DIGIT_00101010 2A +#define HEX_DIGIT_00101011 2B +#define HEX_DIGIT_00101100 2C +#define HEX_DIGIT_00101101 2D +#define HEX_DIGIT_00101110 2E +#define HEX_DIGIT_00101111 2F +#define HEX_DIGIT_00110000 30 +#define HEX_DIGIT_00110001 31 +#define HEX_DIGIT_00110010 32 +#define HEX_DIGIT_00110011 33 +#define HEX_DIGIT_00110100 34 +#define HEX_DIGIT_00110101 35 +#define HEX_DIGIT_00110110 36 +#define HEX_DIGIT_00110111 37 +#define HEX_DIGIT_00111000 38 +#define HEX_DIGIT_00111001 39 +#define HEX_DIGIT_00111010 3A +#define HEX_DIGIT_00111011 3B +#define HEX_DIGIT_00111100 3C +#define HEX_DIGIT_00111101 3D +#define HEX_DIGIT_00111110 3E +#define HEX_DIGIT_00111111 3F +#define HEX_DIGIT_01000000 40 +#define HEX_DIGIT_01000001 41 +#define HEX_DIGIT_01000010 42 +#define HEX_DIGIT_01000011 43 +#define HEX_DIGIT_01000100 44 +#define HEX_DIGIT_01000101 45 +#define HEX_DIGIT_01000110 46 +#define HEX_DIGIT_01000111 47 +#define HEX_DIGIT_01001000 48 +#define HEX_DIGIT_01001001 49 +#define HEX_DIGIT_01001010 4A +#define HEX_DIGIT_01001011 4B +#define HEX_DIGIT_01001100 4C +#define HEX_DIGIT_01001101 4D +#define HEX_DIGIT_01001110 4E +#define HEX_DIGIT_01001111 4F +#define HEX_DIGIT_01010000 50 +#define HEX_DIGIT_01010001 51 +#define HEX_DIGIT_01010010 52 +#define HEX_DIGIT_01010011 53 +#define HEX_DIGIT_01010100 54 +#define HEX_DIGIT_01010101 55 +#define HEX_DIGIT_01010110 56 +#define HEX_DIGIT_01010111 57 +#define HEX_DIGIT_01011000 58 +#define HEX_DIGIT_01011001 59 +#define HEX_DIGIT_01011010 5A +#define HEX_DIGIT_01011011 5B +#define HEX_DIGIT_01011100 5C +#define HEX_DIGIT_01011101 5D +#define HEX_DIGIT_01011110 5E +#define HEX_DIGIT_01011111 5F +#define HEX_DIGIT_01100000 60 +#define HEX_DIGIT_01100001 61 +#define HEX_DIGIT_01100010 62 +#define HEX_DIGIT_01100011 63 +#define HEX_DIGIT_01100100 64 +#define HEX_DIGIT_01100101 65 +#define HEX_DIGIT_01100110 66 +#define HEX_DIGIT_01100111 67 +#define HEX_DIGIT_01101000 68 +#define HEX_DIGIT_01101001 69 +#define HEX_DIGIT_01101010 6A +#define HEX_DIGIT_01101011 6B +#define HEX_DIGIT_01101100 6C +#define HEX_DIGIT_01101101 6D +#define HEX_DIGIT_01101110 6E +#define HEX_DIGIT_01101111 6F +#define HEX_DIGIT_01110000 70 +#define HEX_DIGIT_01110001 71 +#define HEX_DIGIT_01110010 72 +#define HEX_DIGIT_01110011 73 +#define HEX_DIGIT_01110100 74 +#define HEX_DIGIT_01110101 75 +#define HEX_DIGIT_01110110 76 +#define HEX_DIGIT_01110111 77 +#define HEX_DIGIT_01111000 78 +#define HEX_DIGIT_01111001 79 +#define HEX_DIGIT_01111010 7A +#define HEX_DIGIT_01111011 7B +#define HEX_DIGIT_01111100 7C +#define HEX_DIGIT_01111101 7D +#define HEX_DIGIT_01111110 7E +#define HEX_DIGIT_01111111 7F +#define HEX_DIGIT_10000000 80 +#define HEX_DIGIT_10000001 81 +#define HEX_DIGIT_10000010 82 +#define HEX_DIGIT_10000011 83 +#define HEX_DIGIT_10000100 84 +#define HEX_DIGIT_10000101 85 +#define HEX_DIGIT_10000110 86 +#define HEX_DIGIT_10000111 87 +#define HEX_DIGIT_10001000 88 +#define HEX_DIGIT_10001001 89 +#define HEX_DIGIT_10001010 8A +#define HEX_DIGIT_10001011 8B +#define HEX_DIGIT_10001100 8C +#define HEX_DIGIT_10001101 8D +#define HEX_DIGIT_10001110 8E +#define HEX_DIGIT_10001111 8F +#define HEX_DIGIT_10010000 90 +#define HEX_DIGIT_10010001 91 +#define HEX_DIGIT_10010010 92 +#define HEX_DIGIT_10010011 93 +#define HEX_DIGIT_10010100 94 +#define HEX_DIGIT_10010101 95 +#define HEX_DIGIT_10010110 96 +#define HEX_DIGIT_10010111 97 +#define HEX_DIGIT_10011000 98 +#define HEX_DIGIT_10011001 99 +#define HEX_DIGIT_10011010 9A +#define HEX_DIGIT_10011011 9B +#define HEX_DIGIT_10011100 9C +#define HEX_DIGIT_10011101 9D +#define HEX_DIGIT_10011110 9E +#define HEX_DIGIT_10011111 9F +#define HEX_DIGIT_10100000 A0 +#define HEX_DIGIT_10100001 A1 +#define HEX_DIGIT_10100010 A2 +#define HEX_DIGIT_10100011 A3 +#define HEX_DIGIT_10100100 A4 +#define HEX_DIGIT_10100101 A5 +#define HEX_DIGIT_10100110 A6 +#define HEX_DIGIT_10100111 A7 +#define HEX_DIGIT_10101000 A8 +#define HEX_DIGIT_10101001 A9 +#define HEX_DIGIT_10101010 AA +#define HEX_DIGIT_10101011 AB +#define HEX_DIGIT_10101100 AC +#define HEX_DIGIT_10101101 AD +#define HEX_DIGIT_10101110 AE +#define HEX_DIGIT_10101111 AF +#define HEX_DIGIT_10110000 B0 +#define HEX_DIGIT_10110001 B1 +#define HEX_DIGIT_10110010 B2 +#define HEX_DIGIT_10110011 B3 +#define HEX_DIGIT_10110100 B4 +#define HEX_DIGIT_10110101 B5 +#define HEX_DIGIT_10110110 B6 +#define HEX_DIGIT_10110111 B7 +#define HEX_DIGIT_10111000 B8 +#define HEX_DIGIT_10111001 B9 +#define HEX_DIGIT_10111010 BA +#define HEX_DIGIT_10111011 BB +#define HEX_DIGIT_10111100 BC +#define HEX_DIGIT_10111101 BD +#define HEX_DIGIT_10111110 BE +#define HEX_DIGIT_10111111 BF +#define HEX_DIGIT_11000000 C0 +#define HEX_DIGIT_11000001 C1 +#define HEX_DIGIT_11000010 C2 +#define HEX_DIGIT_11000011 C3 +#define HEX_DIGIT_11000100 C4 +#define HEX_DIGIT_11000101 C5 +#define HEX_DIGIT_11000110 C6 +#define HEX_DIGIT_11000111 C7 +#define HEX_DIGIT_11001000 C8 +#define HEX_DIGIT_11001001 C9 +#define HEX_DIGIT_11001010 CA +#define HEX_DIGIT_11001011 CB +#define HEX_DIGIT_11001100 CC +#define HEX_DIGIT_11001101 CD +#define HEX_DIGIT_11001110 CE +#define HEX_DIGIT_11001111 CF +#define HEX_DIGIT_11010000 D0 +#define HEX_DIGIT_11010001 D1 +#define HEX_DIGIT_11010010 D2 +#define HEX_DIGIT_11010011 D3 +#define HEX_DIGIT_11010100 D4 +#define HEX_DIGIT_11010101 D5 +#define HEX_DIGIT_11010110 D6 +#define HEX_DIGIT_11010111 D7 +#define HEX_DIGIT_11011000 D8 +#define HEX_DIGIT_11011001 D9 +#define HEX_DIGIT_11011010 DA +#define HEX_DIGIT_11011011 DB +#define HEX_DIGIT_11011100 DC +#define HEX_DIGIT_11011101 DD +#define HEX_DIGIT_11011110 DE +#define HEX_DIGIT_11011111 DF +#define HEX_DIGIT_11100000 E0 +#define HEX_DIGIT_11100001 E1 +#define HEX_DIGIT_11100010 E2 +#define HEX_DIGIT_11100011 E3 +#define HEX_DIGIT_11100100 E4 +#define HEX_DIGIT_11100101 E5 +#define HEX_DIGIT_11100110 E6 +#define HEX_DIGIT_11100111 E7 +#define HEX_DIGIT_11101000 E8 +#define HEX_DIGIT_11101001 E9 +#define HEX_DIGIT_11101010 EA +#define HEX_DIGIT_11101011 EB +#define HEX_DIGIT_11101100 EC +#define HEX_DIGIT_11101101 ED +#define HEX_DIGIT_11101110 EE +#define HEX_DIGIT_11101111 EF +#define HEX_DIGIT_11110000 F0 +#define HEX_DIGIT_11110001 F1 +#define HEX_DIGIT_11110010 F2 +#define HEX_DIGIT_11110011 F3 +#define HEX_DIGIT_11110100 F4 +#define HEX_DIGIT_11110101 F5 +#define HEX_DIGIT_11110110 F6 +#define HEX_DIGIT_11110111 F7 +#define HEX_DIGIT_11111000 F8 +#define HEX_DIGIT_11111001 F9 +#define HEX_DIGIT_11111010 FA +#define HEX_DIGIT_11111011 FB +#define HEX_DIGIT_11111100 FC +#define HEX_DIGIT_11111101 FD +#define HEX_DIGIT_11111110 FE +#define HEX_DIGIT_11111111 FF + +#if 0 +#pragma mark == Debugging == +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @function CommonServicesTest + + @abstract Unit test. +*/ + +#if( DEBUG ) + #if( TARGET_LANGUAGE_C_LIKE ) + OSStatus CommonServicesTest( void ); + #endif +#endif + +#ifdef __cplusplus + } +#endif + +#endif // __COMMON_SERVICES__ diff --git a/mDNSShared/DebugServices.c b/mDNSShared/DebugServices.c new file mode 100644 index 0000000..164310a --- /dev/null +++ b/mDNSShared/DebugServices.c @@ -0,0 +1,3102 @@ +/* -*- Mode: C; tab-width: 4 -*- + * + * Copyright (c) 1997-2004 Apple Computer, Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + + Change History (most recent first): + +$Log: DebugServices.c,v $ +Revision 1.6 2006/08/14 23:24:56 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + +Revision 1.5 2004/09/17 01:08:57 cheshire +Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h + The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces + declared in that file are ONLY appropriate to single-address-space embedded applications. + For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used. + +Revision 1.4 2004/04/15 08:59:08 bradley +Removed deprecated debug and log levels and replaced them with modern equivalents. + +Revision 1.3 2004/04/08 09:29:55 bradley +Manually do host->network byte order conversion to avoid needing libraries for htons/htonl. Changed +hex dumps to better separate hex and ASCII. Added support for %.8a syntax in DebugSNPrintF for Fibre +Channel addresses (00:11:22:33:44:55:66:77). Fixed a few places where HeaderDoc was incorrect. + +Revision 1.2 2004/03/07 05:59:34 bradley +Sync'd with internal version: Added expect macros, error codes, and CoreServices exclusion. + +Revision 1.1 2004/01/30 02:27:30 bradley +Debugging support for various platforms. + + + To Do: + + - Use StackWalk on Windows to optionally print stack frames. +*/ + +#if 0 +#pragma mark == Includes == +#endif + +//=========================================================================================================================== +// Includes +//=========================================================================================================================== + +#if( !KERNEL ) + #include + #include + #include +#endif + +#include "CommonServices.h" + +#include "DebugServices.h" + +#if( DEBUG ) + +#if( TARGET_OS_VXWORKS ) + #include "intLib.h" +#endif + +#if( TARGET_OS_WIN32 ) + #include + + #if( !TARGET_OS_WINDOWS_CE ) + #include + #include + #endif +#endif + +#if( DEBUG_IDEBUG_ENABLED && TARGET_API_MAC_OSX_KERNEL ) + #include +#endif + +// If MDNS_DEBUGMSGS is defined (even if defined 0), it is aware of mDNS and it is probably safe to include mDNSEmbeddedAPI.h. + +#if( defined( MDNS_DEBUGMSGS ) ) + #include "mDNSEmbeddedAPI.h" +#endif + +#if 0 +#pragma mark == Macros == +#endif + +//=========================================================================================================================== +// Macros +//=========================================================================================================================== + +#define DebugIsPrint( C ) ( ( ( C ) >= 0x20 ) && ( ( C ) <= 0x7E ) ) + +#if 0 +#pragma mark == Prototypes == +#endif + +//=========================================================================================================================== +// Prototypes +//=========================================================================================================================== + +static OSStatus DebugPrint( DebugLevel inLevel, char *inData, size_t inSize ); + +// fprintf + +#if( DEBUG_FPRINTF_ENABLED ) + static OSStatus DebugFPrintFInit( DebugOutputTypeFlags inFlags, const char *inFilename ); + static void DebugFPrintFPrint( char *inData, size_t inSize ); +#endif + +// iDebug (Mac OS X user and kernel) + +#if( DEBUG_IDEBUG_ENABLED ) + static OSStatus DebugiDebugInit( void ); + static void DebugiDebugPrint( char *inData, size_t inSize ); +#endif + +// kprintf (Mac OS X Kernel) + +#if( DEBUG_KPRINTF_ENABLED ) + static void DebugKPrintFPrint( char *inData, size_t inSize ); +#endif + +// Mac OS X IOLog (Mac OS X Kernel) + +#if( DEBUG_MAC_OS_X_IOLOG_ENABLED ) + static void DebugMacOSXIOLogPrint( char *inData, size_t inSize ); +#endif + +// Mac OS X Log + +#if( TARGET_OS_MAC ) + static OSStatus DebugMacOSXLogInit( void ); + static void DebugMacOSXLogPrint( char *inData, size_t inSize ); +#endif + +// Windows Debugger + +#if( TARGET_OS_WIN32 ) + static void DebugWindowsDebuggerPrint( char *inData, size_t inSize ); +#endif + +// Windows Event Log + +#if( TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE ) + static OSStatus DebugWindowsEventLogInit( const char *inName, HMODULE inModule ); + static void DebugWindowsEventLogPrint( DebugLevel inLevel, char *inData, size_t inSize ); +#endif + +// DebugLib support + +#if( DEBUG_CORE_SERVICE_ASSERTS_ENABLED ) + static pascal void + DebugAssertOutputHandler( + OSType inComponentSignature, + UInt32 inOptions, + const char * inAssertionString, + const char * inExceptionString, + const char * inErrorString, + const char * inFileName, + long inLineNumber, + void * inValue, + ConstStr255Param inOutputMsg ); +#endif + +// Utilities + +static char * DebugNumVersionToString( uint32_t inVersion, char *inString ); + +#if( TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE ) + static void DebugWinEnableConsole( void ); +#endif + +#if( TARGET_OS_WIN32 ) + static TCHAR * + DebugWinCharToTCharString( + const char * inCharString, + size_t inCharCount, + TCHAR * outTCharString, + size_t inTCharCountMax, + size_t * outTCharCount ); +#endif + +#if 0 +#pragma mark == Globals == +#endif + +//=========================================================================================================================== +// Private Globals +//=========================================================================================================================== + +#if( TARGET_OS_VXWORKS ) + // TCP States for inetstatShow. + + extern char ** pTcpstates; // defined in tcpLib.c + + const char * kDebugTCPStates[] = + { + "(0) TCPS_CLOSED", + "(1) TCPS_LISTEN", + "(2) TCPS_SYN_SENT", + "(3) TCPS_SYN_RECEIVED", + "(4) TCPS_ESTABLISHED", + "(5) TCPS_CLOSE_WAIT", + "(6) TCPS_FIN_WAIT_1", + "(7) TCPS_CLOSING", + "(8) TCPS_LAST_ACK", + "(9) TCPS_FIN_WAIT_2", + "(10) TCPS_TIME_WAIT", + }; +#endif + +// General + +static bool gDebugInitialized = false; +static DebugOutputType gDebugOutputType = kDebugOutputTypeNone; +static DebugLevel gDebugPrintLevelMin = kDebugLevelInfo; +static DebugLevel gDebugPrintLevelMax = kDebugLevelMax; +static DebugLevel gDebugBreakLevel = kDebugLevelAssert; +#if( DEBUG_CORE_SERVICE_ASSERTS_ENABLED ) + static DebugAssertOutputHandlerUPP gDebugAssertOutputHandlerUPP = NULL; +#endif + +// Custom + +static DebugOutputFunctionPtr gDebugCustomOutputFunction = NULL; +static void * gDebugCustomOutputContext = NULL; + +// fprintf + +#if( DEBUG_FPRINTF_ENABLED ) + static FILE * gDebugFPrintFFile = NULL; +#endif + +// MacOSXLog + +#if( TARGET_OS_MAC ) + typedef int ( *DebugMacOSXLogFunctionPtr )( const char *inFormat, ... ); + + static DebugMacOSXLogFunctionPtr gDebugMacOSXLogFunction = NULL; +#endif + +// WindowsEventLog + + +#if( TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE ) + static HANDLE gDebugWindowsEventLogEventSource = NULL; +#endif + +#if 0 +#pragma mark - +#pragma mark == General == +#endif + +//=========================================================================================================================== +// DebugInitialize +//=========================================================================================================================== + +DEBUG_EXPORT OSStatus DebugInitialize( DebugOutputType inType, ... ) +{ + OSStatus err; + DebugOutputType type; + va_list args; + + va_start( args, inType ); + +#if( TARGET_OS_VXWORKS ) + // Set up the TCP state strings if they are not already set up by VxWorks (normally not set up for some reason). + + if( !pTcpstates ) + { + pTcpstates = (char **) kDebugTCPStates; + } +#endif + + // Set up DebugLib stuff (if building with Debugging.h). + +#if( DEBUG_CORE_SERVICE_ASSERTS_ENABLED ) + if( !gDebugAssertOutputHandlerUPP ) + { + gDebugAssertOutputHandlerUPP = NewDebugAssertOutputHandlerUPP( DebugAssertOutputHandler ); + check( gDebugAssertOutputHandlerUPP ); + if( gDebugAssertOutputHandlerUPP ) + { + InstallDebugAssertOutputHandler( gDebugAssertOutputHandlerUPP ); + } + } +#endif + + // Pre-process meta-output kind to pick an appropriate output kind for the platform. + + type = inType; + if( type == kDebugOutputTypeMetaConsole ) + { + #if( TARGET_OS_MAC ) + type = kDebugOutputTypeMacOSXLog; + #elif( TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE ) + #if( DEBUG_FPRINTF_ENABLED ) + type = kDebugOutputTypeFPrintF; + #else + type = kDebugOutputTypeWindowsDebugger; + #endif + #elif( TARGET_API_MAC_OSX_KERNEL ) + #if( DEBUG_MAC_OS_X_IOLOG_ENABLED ) + type = kDebugOutputTypeMacOSXIOLog; + #elif( DEBUG_IDEBUG_ENABLED ) + type = kDebugOutputTypeiDebug; + #elif( DEBUG_KPRINTF_ENABLED ) + type = kDebugOutputTypeKPrintF; + #endif + #elif( TARGET_OS_VXWORKS ) + #if( DEBUG_FPRINTF_ENABLED ) + type = kDebugOutputTypeFPrintF; + #else + #error target is VxWorks, but fprintf output is disabled + #endif + #else + #if( DEBUG_FPRINTF_ENABLED ) + type = kDebugOutputTypeFPrintF; + #endif + #endif + } + + // Process output kind. + + gDebugOutputType = type; + switch( type ) + { + case kDebugOutputTypeNone: + err = kNoErr; + break; + + case kDebugOutputTypeCustom: + gDebugCustomOutputFunction = va_arg( args, DebugOutputFunctionPtr ); + gDebugCustomOutputContext = va_arg( args, void * ); + err = kNoErr; + break; + +#if( DEBUG_FPRINTF_ENABLED ) + case kDebugOutputTypeFPrintF: + if( inType == kDebugOutputTypeMetaConsole ) + { + err = DebugFPrintFInit( kDebugOutputTypeFlagsStdErr, NULL ); + } + else + { + DebugOutputTypeFlags flags; + const char * filename; + + flags = (DebugOutputTypeFlags) va_arg( args, unsigned int ); + if( ( flags & kDebugOutputTypeFlagsTypeMask ) == kDebugOutputTypeFlagsFile ) + { + filename = va_arg( args, const char * ); + } + else + { + filename = NULL; + } + err = DebugFPrintFInit( flags, filename ); + } + break; +#endif + +#if( DEBUG_IDEBUG_ENABLED ) + case kDebugOutputTypeiDebug: + err = DebugiDebugInit(); + break; +#endif + +#if( DEBUG_KPRINTF_ENABLED ) + case kDebugOutputTypeKPrintF: + err = kNoErr; + break; +#endif + +#if( DEBUG_MAC_OS_X_IOLOG_ENABLED ) + case kDebugOutputTypeMacOSXIOLog: + err = kNoErr; + break; +#endif + +#if( TARGET_OS_MAC ) + case kDebugOutputTypeMacOSXLog: + err = DebugMacOSXLogInit(); + break; +#endif + +#if( TARGET_OS_WIN32 ) + case kDebugOutputTypeWindowsDebugger: + err = kNoErr; + break; +#endif + +#if( TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE ) + case kDebugOutputTypeWindowsEventLog: + { + const char * name; + HMODULE module; + + name = va_arg( args, const char * ); + module = va_arg( args, HMODULE ); + err = DebugWindowsEventLogInit( name, module ); + } + break; +#endif + + default: + err = kParamErr; + goto exit; + } + gDebugInitialized = true; + +exit: + va_end( args ); + return( err ); +} + +//=========================================================================================================================== +// DebugFinalize +//=========================================================================================================================== + +DEBUG_EXPORT void DebugFinalize( void ) +{ +#if( DEBUG_CORE_SERVICE_ASSERTS_ENABLED ) + check( gDebugAssertOutputHandlerUPP ); + if( gDebugAssertOutputHandlerUPP ) + { + InstallDebugAssertOutputHandler( NULL ); + DisposeDebugAssertOutputHandlerUPP( gDebugAssertOutputHandlerUPP ); + gDebugAssertOutputHandlerUPP = NULL; + } +#endif +} + +//=========================================================================================================================== +// DebugGetProperty +//=========================================================================================================================== + +DEBUG_EXPORT OSStatus DebugGetProperty( DebugPropertyTag inTag, ... ) +{ + OSStatus err; + va_list args; + DebugLevel * level; + + va_start( args, inTag ); + switch( inTag ) + { + case kDebugPropertyTagPrintLevelMin: + level = va_arg( args, DebugLevel * ); + *level = gDebugPrintLevelMin; + err = kNoErr; + break; + + case kDebugPropertyTagPrintLevelMax: + level = va_arg( args, DebugLevel * ); + *level = gDebugPrintLevelMax; + err = kNoErr; + break; + + case kDebugPropertyTagBreakLevel: + level = va_arg( args, DebugLevel * ); + *level = gDebugBreakLevel; + err = kNoErr; + break; + + default: + err = kUnsupportedErr; + break; + } + va_end( args ); + return( err ); +} + +//=========================================================================================================================== +// DebugSetProperty +//=========================================================================================================================== + +DEBUG_EXPORT OSStatus DebugSetProperty( DebugPropertyTag inTag, ... ) +{ + OSStatus err; + va_list args; + DebugLevel level; + + va_start( args, inTag ); + switch( inTag ) + { + case kDebugPropertyTagPrintLevelMin: + level = va_arg( args, DebugLevel ); + gDebugPrintLevelMin = level; + err = kNoErr; + break; + + case kDebugPropertyTagPrintLevelMax: + level = va_arg( args, DebugLevel ); + gDebugPrintLevelMax = level; + err = kNoErr; + break; + + case kDebugPropertyTagBreakLevel: + level = va_arg( args, DebugLevel ); + gDebugBreakLevel = level; + err = kNoErr; + break; + + default: + err = kUnsupportedErr; + break; + } + va_end( args ); + return( err ); +} + +#if 0 +#pragma mark - +#pragma mark == Output == +#endif + +//=========================================================================================================================== +// DebugPrintF +//=========================================================================================================================== + +DEBUG_EXPORT size_t DebugPrintF( DebugLevel inLevel, const char *inFormat, ... ) +{ + va_list args; + size_t n; + + // Skip if the level is not in the enabled range.. + + if( ( inLevel < gDebugPrintLevelMin ) || ( inLevel > gDebugPrintLevelMax ) ) + { + n = 0; + goto exit; + } + + va_start( args, inFormat ); + n = DebugPrintFVAList( inLevel, inFormat, args ); + va_end( args ); + +exit: + return( n ); +} + +//=========================================================================================================================== +// DebugPrintFVAList +//=========================================================================================================================== + +DEBUG_EXPORT size_t DebugPrintFVAList( DebugLevel inLevel, const char *inFormat, va_list inArgs ) +{ + size_t n; + char buffer[ 512 ]; + + // Skip if the level is not in the enabled range.. + + if( ( inLevel < gDebugPrintLevelMin ) || ( inLevel > gDebugPrintLevelMax ) ) + { + n = 0; + goto exit; + } + + n = DebugSNPrintFVAList( buffer, sizeof( buffer ), inFormat, inArgs ); + DebugPrint( inLevel, buffer, (size_t) n ); + +exit: + return( n ); +} + +//=========================================================================================================================== +// DebugPrint +//=========================================================================================================================== + +static OSStatus DebugPrint( DebugLevel inLevel, char *inData, size_t inSize ) +{ + OSStatus err; + + // Skip if the level is not in the enabled range.. + + if( ( inLevel < gDebugPrintLevelMin ) || ( inLevel > gDebugPrintLevelMax ) ) + { + err = kRangeErr; + goto exit; + } + + // Printing is not safe at interrupt time so check for this and warn with an interrupt safe mechanism (if available). + + if( DebugTaskLevel() & kDebugInterruptLevelMask ) + { + #if( TARGET_OS_VXWORKS ) + logMsg( "\ncannot print at interrupt time\n\n", 1, 2, 3, 4, 5, 6 ); + #endif + + err = kExecutionStateErr; + goto exit; + } + + // Initialize the debugging library if it hasn't already been initialized (allows for zero-config usage). + + if( !gDebugInitialized ) + { + debug_initialize( kDebugOutputTypeMetaConsole ); + } + + // Print based on the current output type. + + switch( gDebugOutputType ) + { + case kDebugOutputTypeNone: + break; + + case kDebugOutputTypeCustom: + if( gDebugCustomOutputFunction ) + { + gDebugCustomOutputFunction( inData, inSize, gDebugCustomOutputContext ); + } + break; + +#if( DEBUG_FPRINTF_ENABLED ) + case kDebugOutputTypeFPrintF: + DebugFPrintFPrint( inData, inSize ); + break; +#endif + +#if( DEBUG_IDEBUG_ENABLED ) + case kDebugOutputTypeiDebug: + DebugiDebugPrint( inData, inSize ); + break; +#endif + +#if( DEBUG_KPRINTF_ENABLED ) + case kDebugOutputTypeKPrintF: + DebugKPrintFPrint( inData, inSize ); + break; +#endif + +#if( DEBUG_MAC_OS_X_IOLOG_ENABLED ) + case kDebugOutputTypeMacOSXIOLog: + DebugMacOSXIOLogPrint( inData, inSize ); + break; +#endif + +#if( TARGET_OS_MAC ) + case kDebugOutputTypeMacOSXLog: + DebugMacOSXLogPrint( inData, inSize ); + break; +#endif + +#if( TARGET_OS_WIN32 ) + case kDebugOutputTypeWindowsDebugger: + DebugWindowsDebuggerPrint( inData, inSize ); + break; +#endif + +#if( TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE ) + case kDebugOutputTypeWindowsEventLog: + DebugWindowsEventLogPrint( inLevel, inData, inSize ); + break; +#endif + + default: + break; + } + err = kNoErr; + +exit: + return( err ); +} + +//=========================================================================================================================== +// DebugPrintAssert +// +// Warning: This routine relies on several of the strings being string constants that will exist forever because the +// underlying logMsg API that does the printing is asynchronous so it cannot use temporary/stack-based +// pointer variables (e.g. local strings). The debug macros that invoke this function only use constant +// constant strings, but if this function is invoked directly from other places, it must use constant strings. +//=========================================================================================================================== + +DEBUG_EXPORT void + DebugPrintAssert( + int_least32_t inErrorCode, + const char * inAssertString, + const char * inMessage, + const char * inFilename, + int_least32_t inLineNumber, + const char * inFunction ) +{ + // Skip if the level is not in the enabled range.. + + if( ( kDebugLevelAssert < gDebugPrintLevelMin ) || ( kDebugLevelAssert > gDebugPrintLevelMax ) ) + { + return; + } + + if( inErrorCode != 0 ) + { + DebugPrintF( + kDebugLevelAssert, + "\n" + "[ASSERT] error: %ld (%m)\n" + "[ASSERT] where: \"%s\", line %ld, \"%s\"\n" + "\n", + inErrorCode, inErrorCode, + inFilename ? inFilename : "", + inLineNumber, + inFunction ? inFunction : "" ); + } + else + { + DebugPrintF( + kDebugLevelAssert, + "\n" + "[ASSERT] assert: \"%s\" %s\n" + "[ASSERT] where: \"%s\", line %ld, \"%s\"\n" + "\n", + inAssertString ? inAssertString : "", + inMessage ? inMessage : "", + inFilename ? inFilename : "", + inLineNumber, + inFunction ? inFunction : "" ); + } + + // Break into the debugger if enabled. + + #if( TARGET_OS_WIN32 ) + if( gDebugBreakLevel <= kDebugLevelAssert ) + { + if( IsDebuggerPresent() ) + { + DebugBreak(); + } + } + #endif +} + +#if 0 +#pragma mark - +#endif + +#if( DEBUG_FPRINTF_ENABLED ) +//=========================================================================================================================== +// DebugFPrintFInit +//=========================================================================================================================== + +static OSStatus DebugFPrintFInit( DebugOutputTypeFlags inFlags, const char *inFilename ) +{ + OSStatus err; + DebugOutputTypeFlags typeFlags; + + typeFlags = inFlags & kDebugOutputTypeFlagsTypeMask; + if( typeFlags == kDebugOutputTypeFlagsStdOut ) + { + #if( TARGET_OS_WIN32 ) + DebugWinEnableConsole(); + #endif + + gDebugFPrintFFile = stdout; + } + else if( typeFlags == kDebugOutputTypeFlagsStdErr ) + { + #if( TARGET_OS_WIN32 ) + DebugWinEnableConsole(); + #endif + + gDebugFPrintFFile = stdout; + } + else if( typeFlags == kDebugOutputTypeFlagsFile ) + { + require_action_quiet( inFilename && ( *inFilename != '\0' ), exit, err = kOpenErr ); + + gDebugFPrintFFile = fopen( inFilename, "a" ); + require_action_quiet( gDebugFPrintFFile, exit, err = kOpenErr ); + } + else + { + err = kParamErr; + goto exit; + } + err = kNoErr; + +exit: + return( err ); +} + +//=========================================================================================================================== +// DebugFPrintFPrint +//=========================================================================================================================== + +static void DebugFPrintFPrint( char *inData, size_t inSize ) +{ + char * p; + char * q; + + // Convert \r to \n. fprintf will interpret \n and convert to whatever is appropriate for the platform. + + p = inData; + q = p + inSize; + while( p < q ) + { + if( *p == '\r' ) + { + *p = '\n'; + } + ++p; + } + + // Write the data and flush. + + if( gDebugFPrintFFile ) + { + fprintf( gDebugFPrintFFile, "%.*s", (int) inSize, inData ); + fflush( gDebugFPrintFFile ); + } +} +#endif // DEBUG_FPRINTF_ENABLED + +#if( DEBUG_IDEBUG_ENABLED ) +//=========================================================================================================================== +// DebugiDebugInit +//=========================================================================================================================== + +static OSStatus DebugiDebugInit( void ) +{ + OSStatus err; + + #if( TARGET_API_MAC_OSX_KERNEL ) + + extern uint32_t * _giDebugReserved1; + + // Emulate the iDebugSetOutputType macro in iDebugServices.h. + // Note: This is not thread safe, but neither is iDebugServices.h nor iDebugKext. + + if( !_giDebugReserved1 ) + { + _giDebugReserved1 = (uint32_t *) IOMalloc( sizeof( uint32_t ) ); + require_action_quiet( _giDebugReserved1, exit, err = kNoMemoryErr ); + } + *_giDebugReserved1 = 0x00010000U; + err = kNoErr; +exit: + #else + + __private_extern__ void iDebugSetOutputTypeInternal( uint32_t inType ); + + iDebugSetOutputTypeInternal( 0x00010000U ); + err = kNoErr; + + #endif + + return( err ); +} + +//=========================================================================================================================== +// DebugiDebugPrint +//=========================================================================================================================== + +static void DebugiDebugPrint( char *inData, size_t inSize ) +{ + #if( TARGET_API_MAC_OSX_KERNEL ) + + // Locally declared here so we do not need to include iDebugKext.h. + // Note: IOKit uses a global namespace for all code and only a partial link occurs at build time. When the + // KEXT is loaded, the runtime linker will link in this extern'd symbol (assuming iDebug is present). + // _giDebugLogInternal is actually part of IOKit proper so this should link even if iDebug is not present. + + typedef void ( *iDebugLogFunctionPtr )( uint32_t inLevel, uint32_t inTag, const char *inFormat, ... ); + + extern iDebugLogFunctionPtr _giDebugLogInternal; + + if( _giDebugLogInternal ) + { + _giDebugLogInternal( 0, 0, "%.*s", (int) inSize, inData ); + } + + #else + + __private_extern__ void iDebugLogInternal( uint32_t inLevel, uint32_t inTag, const char *inFormat, ... ); + + iDebugLogInternal( 0, 0, "%.*s", (int) inSize, inData ); + + #endif +} +#endif + +#if( DEBUG_KPRINTF_ENABLED ) +//=========================================================================================================================== +// DebugKPrintFPrint +//=========================================================================================================================== + +static void DebugKPrintFPrint( char *inData, size_t inSize ) +{ + extern void kprintf( const char *inFormat, ... ); + + kprintf( "%.*s", (int) inSize, inData ); +} +#endif + +#if( DEBUG_MAC_OS_X_IOLOG_ENABLED ) +//=========================================================================================================================== +// DebugMacOSXIOLogPrint +//=========================================================================================================================== + +static void DebugMacOSXIOLogPrint( char *inData, size_t inSize ) +{ + extern void IOLog( const char *inFormat, ... ); + + IOLog( "%.*s", (int) inSize, inData ); +} +#endif + +#if( TARGET_OS_MAC ) +//=========================================================================================================================== +// DebugMacOSXLogInit +//=========================================================================================================================== + +static OSStatus DebugMacOSXLogInit( void ) +{ + OSStatus err; + CFStringRef path; + CFURLRef url; + CFBundleRef bundle; + CFStringRef functionName; + void * functionPtr; + + bundle = NULL; + + // Create a bundle reference for System.framework. + + path = CFSTR( "/System/Library/Frameworks/System.framework" ); + url = CFURLCreateWithFileSystemPath( NULL, path, kCFURLPOSIXPathStyle, true ); + require_action_quiet( url, exit, err = memFullErr ); + + bundle = CFBundleCreate( NULL, url ); + CFRelease( url ); + require_action_quiet( bundle, exit, err = memFullErr ); + + // Get a ptr to the system's "printf" function from System.framework. + + functionName = CFSTR( "printf" ); + functionPtr = CFBundleGetFunctionPointerForName( bundle, functionName ); + require_action_quiet( functionPtr, exit, err = memFullErr ); + + // Success! Note: The bundle cannot be released because it would invalidate the function ptr. + + gDebugMacOSXLogFunction = (DebugMacOSXLogFunctionPtr) functionPtr; + bundle = NULL; + err = noErr; + +exit: + if( bundle ) + { + CFRelease( bundle ); + } + return( err ); +} + +//=========================================================================================================================== +// DebugMacOSXLogPrint +//=========================================================================================================================== + +static void DebugMacOSXLogPrint( char *inData, size_t inSize ) +{ + if( gDebugMacOSXLogFunction ) + { + gDebugMacOSXLogFunction( "%.*s", (int) inSize, inData ); + } +} +#endif + +#if( TARGET_OS_WIN32 ) +//=========================================================================================================================== +// DebugWindowsDebuggerPrint +//=========================================================================================================================== + +void DebugWindowsDebuggerPrint( char *inData, size_t inSize ) +{ + TCHAR buffer[ 512 ]; + const char * src; + const char * end; + TCHAR * dst; + char c; + + // Copy locally and null terminate the string. This also converts from char to TCHAR in case we are + // building with UNICODE enabled since the input is always char. Also convert \r to \n in the process. + + src = inData; + if( inSize >= sizeof_array( buffer ) ) + { + inSize = sizeof_array( buffer ) - 1; + } + end = src + inSize; + dst = buffer; + while( src < end ) + { + c = *src++; + if( c == '\r' ) + { + c = '\n'; + } + *dst++ = (TCHAR) c; + } + *dst = 0; + + // Print out the string to the debugger. + + OutputDebugString( buffer ); +} +#endif + +#if( TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE ) +//=========================================================================================================================== +// DebugWindowsEventLogInit +//=========================================================================================================================== + +static OSStatus DebugWindowsEventLogInit( const char *inName, HMODULE inModule ) +{ + OSStatus err; + HKEY key; + TCHAR name[ 128 ]; + const char * src; + TCHAR path[ MAX_PATH ]; + size_t size; + DWORD typesSupported; + DWORD n; + + key = NULL; + + // Use a default name if needed then convert the name to TCHARs so it works on ANSI or Unicode builds. + + if( !inName || ( *inName == '\0' ) ) + { + inName = "DefaultApp"; + } + DebugWinCharToTCharString( inName, kSizeCString, name, sizeof( name ), NULL ); + + // Build the path string using the fixed registry path and app name. + + src = "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\"; + DebugWinCharToTCharString( src, kSizeCString, path, sizeof_array( path ), &size ); + DebugWinCharToTCharString( inName, kSizeCString, path + size, sizeof_array( path ) - size, NULL ); + + // Add/Open the source name as a sub-key under the Application key in the EventLog registry key. + + err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, path, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &key, NULL ); + require_noerr_quiet( err, exit ); + + // Set the path in the EventMessageFile subkey. Add 1 to the TCHAR count to include the null terminator. + + n = GetModuleFileName( inModule, path, sizeof_array( path ) ); + err = translate_errno( n > 0, (OSStatus) GetLastError(), kParamErr ); + require_noerr_quiet( err, exit ); + n += 1; + n *= sizeof( TCHAR ); + + err = RegSetValueEx( key, TEXT( "EventMessageFile" ), 0, REG_EXPAND_SZ, (const LPBYTE) path, n ); + require_noerr_quiet( err, exit ); + + // Set the supported event types in the TypesSupported subkey. + + typesSupported = EVENTLOG_SUCCESS | EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE | + EVENTLOG_AUDIT_SUCCESS | EVENTLOG_AUDIT_FAILURE; + err = RegSetValueEx( key, TEXT( "TypesSupported" ), 0, REG_DWORD, (const LPBYTE) &typesSupported, sizeof( DWORD ) ); + require_noerr_quiet( err, exit ); + + // Set up the event source. + + gDebugWindowsEventLogEventSource = RegisterEventSource( NULL, name ); + err = translate_errno( gDebugWindowsEventLogEventSource, (OSStatus) GetLastError(), kParamErr ); + require_noerr_quiet( err, exit ); + +exit: + if( key ) + { + RegCloseKey( key ); + } + return( err ); +} + +//=========================================================================================================================== +// DebugWindowsEventLogPrint +//=========================================================================================================================== + +static void DebugWindowsEventLogPrint( DebugLevel inLevel, char *inData, size_t inSize ) +{ + WORD type; + TCHAR buffer[ 512 ]; + const char * src; + const char * end; + TCHAR * dst; + char c; + const TCHAR * array[ 1 ]; + + // Map the debug level to a Windows EventLog type. + + if( inLevel <= kDebugLevelNotice ) + { + type = EVENTLOG_INFORMATION_TYPE; + } + else if( inLevel <= kDebugLevelWarning ) + { + type = EVENTLOG_WARNING_TYPE; + } + else + { + type = EVENTLOG_ERROR_TYPE; + } + + // Copy locally and null terminate the string. This also converts from char to TCHAR in case we are + // building with UNICODE enabled since the input is always char. Also convert \r to \n in the process. + + src = inData; + if( inSize >= sizeof_array( buffer ) ) + { + inSize = sizeof_array( buffer ) - 1; + } + end = src + inSize; + dst = buffer; + while( src < end ) + { + c = *src++; + if( c == '\r' ) + { + c = '\n'; + } + *dst++ = (TCHAR) c; + } + *dst = 0; + + // Add the the string to the event log. + + array[ 0 ] = buffer; + if( gDebugWindowsEventLogEventSource ) + { + ReportEvent( gDebugWindowsEventLogEventSource, type, 0, 0x20000001L, NULL, 1, 0, array, NULL ); + } +} +#endif // TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE + +#if( DEBUG_CORE_SERVICE_ASSERTS_ENABLED ) +//=========================================================================================================================== +// DebugAssertOutputHandler +//=========================================================================================================================== + +static pascal void + DebugAssertOutputHandler( + OSType inComponentSignature, + UInt32 inOptions, + const char * inAssertString, + const char * inExceptionString, + const char * inErrorString, + const char * inFileName, + long inLineNumber, + void * inValue, + ConstStr255Param inOutputMsg ) +{ + DEBUG_UNUSED( inComponentSignature ); + DEBUG_UNUSED( inOptions ); + DEBUG_UNUSED( inExceptionString ); + DEBUG_UNUSED( inValue ); + DEBUG_UNUSED( inOutputMsg ); + + DebugPrintAssert( 0, inAssertString, inErrorString, inFileName, (int_least32_t) inLineNumber, "" ); +} +#endif + +#if 0 +#pragma mark - +#pragma mark == Utilities == +#endif + +//=========================================================================================================================== +// DebugSNPrintF +// +// Stolen from mDNS.c's mDNS_snprintf/mDNS_vsnprintf with the following changes: +// +// Changed names to avoid name collisions with the mDNS versions. +// Changed types to standard C types since mDNSEmbeddedAPI.h may not be available. +// Conditionalized mDNS stuff so it can be used with or with mDNSEmbeddedAPI.h. +// Added 64-bit support for %d (%lld), %i (%lli), %u (%llu), %o (%llo), %x (%llx), and %b (%llb). +// Added %@ - Cocoa/CoreFoundation object. Param is the object. Strings are used directly. Others use CFCopyDescription. +// Added %.8a - FIbre Channel address. Arg=ptr to address. +// Added %##a - IPv4 (if AF_INET defined) or IPv6 (if AF_INET6 defined) sockaddr. Arg=ptr to sockaddr. +// Added %b - Binary representation of integer (e.g. 01101011). Modifiers and arg=the same as %d, %x, etc. +// Added %C - Mac-style FourCharCode (e.g. 'APPL'). Arg=32-bit value to print as a Mac-style FourCharCode. +// Added %H - Hex Dump (e.g. "\x6b\xa7" -> "6B A7"). 1st arg=ptr, 2nd arg=size, 3rd arg=max size. +// Added %#H - Hex Dump & ASCII (e.g. "\x41\x62" -> "6B A7 'Ab'"). 1st arg=ptr, 2nd arg=size, 3rd arg=max size. +// Added %m - Error Message (e.g. 0 -> "kNoErr"). Modifiers and error code args are the same as %d, %x, etc. +// Added %S - UTF-16 string. Host order if no BOM. Precision is UTF-16 char count. BOM counts in any precision. Arg=ptr. +// Added %#S - Big Endian UTF-16 string (unless BOM overrides). Otherwise the same as %S. +// Added %##S - Little Endian UTF-16 string (unless BOM overrides). Otherwise the same as %S. +// Added %U - Universally Unique Identifier (UUID) (e.g. 6ba7b810-9dad-11d1-80b4-00c04fd430c8). Arg=ptr to 16-byte UUID. +//=========================================================================================================================== + +DEBUG_EXPORT size_t DebugSNPrintF(char *sbuffer, size_t buflen, const char *fmt, ...) + { + size_t length; + + va_list ptr; + va_start(ptr,fmt); + length = DebugSNPrintFVAList(sbuffer, buflen, fmt, ptr); + va_end(ptr); + + return(length); + } + +//=========================================================================================================================== +// DebugSNPrintFVAList - va_list version of DebugSNPrintF. See DebugSNPrintF for more info. +//=========================================================================================================================== + +DEBUG_EXPORT size_t DebugSNPrintFVAList(char *sbuffer, size_t buflen, const char *fmt, va_list arg) + { + static const struct DebugSNPrintF_format + { + unsigned leftJustify : 1; + unsigned forceSign : 1; + unsigned zeroPad : 1; + unsigned havePrecision : 1; + unsigned hSize : 1; + char lSize; + char altForm; + char sign; // +, - or space + unsigned int fieldWidth; + unsigned int precision; + } DebugSNPrintF_format_default = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + + size_t nwritten = 0; + int c; + if (buflen == 0) return(0); + buflen--; // Pre-reserve one space in the buffer for the terminating nul + if (buflen == 0) goto exit; + + for (c = *fmt; c != 0; c = *++fmt) + { + if (c != '%') + { + *sbuffer++ = (char)c; + if (++nwritten >= buflen) goto exit; + } + else + { + size_t i=0, j; + // The mDNS Vsprintf Argument Conversion Buffer is used as a temporary holding area for + // generating decimal numbers, hexdecimal numbers, IP addresses, domain name strings, etc. + // The size needs to be enough for a 256-byte domain name plus some error text. + #define mDNS_VACB_Size 300 + char mDNS_VACB[mDNS_VACB_Size]; + #define mDNS_VACB_Lim (&mDNS_VACB[mDNS_VACB_Size]) + #define mDNS_VACB_Remain(s) ((size_t)(mDNS_VACB_Lim - s)) + char *s = mDNS_VACB_Lim; + const char *digits = "0123456789ABCDEF"; + struct DebugSNPrintF_format F = DebugSNPrintF_format_default; + + for(;;) // decode flags + { + c = *++fmt; + if (c == '-') F.leftJustify = 1; + else if (c == '+') F.forceSign = 1; + else if (c == ' ') F.sign = ' '; + else if (c == '#') F.altForm++; + else if (c == '0') F.zeroPad = 1; + else break; + } + + if (c == '*') // decode field width + { + int f = va_arg(arg, int); + if (f < 0) { f = -f; F.leftJustify = 1; } + F.fieldWidth = (unsigned int)f; + c = *++fmt; + } + else + { + for (; c >= '0' && c <= '9'; c = *++fmt) + F.fieldWidth = (10 * F.fieldWidth) + (c - '0'); + } + + if (c == '.') // decode precision + { + if ((c = *++fmt) == '*') + { F.precision = va_arg(arg, unsigned int); c = *++fmt; } + else for (; c >= '0' && c <= '9'; c = *++fmt) + F.precision = (10 * F.precision) + (c - '0'); + F.havePrecision = 1; + } + + if (F.leftJustify) F.zeroPad = 0; + + conv: + switch (c) // perform appropriate conversion + { + #if TYPE_LONGLONG_NATIVE + unsigned_long_long_compat n; + unsigned_long_long_compat base; + #else + unsigned long n; + unsigned long base; + #endif + case 'h' : F.hSize = 1; c = *++fmt; goto conv; + case 'l' : // fall through + case 'L' : F.lSize++; c = *++fmt; goto conv; + case 'd' : + case 'i' : base = 10; + goto canBeSigned; + case 'u' : base = 10; + goto notSigned; + case 'o' : base = 8; + goto notSigned; + case 'b' : base = 2; + goto notSigned; + case 'p' : n = va_arg(arg, uintptr_t); + F.havePrecision = 1; + F.precision = (sizeof(uintptr_t) == 4) ? 8 : 16; + F.sign = 0; + base = 16; + c = 'x'; + goto number; + case 'x' : digits = "0123456789abcdef"; + case 'X' : base = 16; + goto notSigned; + canBeSigned: + #if TYPE_LONGLONG_NATIVE + if (F.lSize == 1) n = (unsigned_long_long_compat)va_arg(arg, long); + else if (F.lSize == 2) n = (unsigned_long_long_compat)va_arg(arg, long_long_compat); + else n = (unsigned_long_long_compat)va_arg(arg, int); + #else + if (F.lSize == 1) n = (unsigned long)va_arg(arg, long); + else if (F.lSize == 2) goto exit; + else n = (unsigned long)va_arg(arg, int); + #endif + if (F.hSize) n = (short) n; + #if TYPE_LONGLONG_NATIVE + if ((long_long_compat) n < 0) { n = (unsigned_long_long_compat)-(long_long_compat)n; F.sign = '-'; } + #else + if ((long) n < 0) { n = (unsigned long)-(long)n; F.sign = '-'; } + #endif + else if (F.forceSign) F.sign = '+'; + goto number; + + notSigned: if (F.lSize == 1) n = va_arg(arg, unsigned long); + else if (F.lSize == 2) + { + #if TYPE_LONGLONG_NATIVE + n = va_arg(arg, unsigned_long_long_compat); + #else + goto exit; + #endif + } + else n = va_arg(arg, unsigned int); + if (F.hSize) n = (unsigned short) n; + F.sign = 0; + goto number; + + number: if (!F.havePrecision) + { + if (F.zeroPad) + { + F.precision = F.fieldWidth; + if (F.altForm) F.precision -= 2; + if (F.sign) --F.precision; + } + if (F.precision < 1) F.precision = 1; + } + if (F.precision > mDNS_VACB_Size - 1) + F.precision = mDNS_VACB_Size - 1; + for (i = 0; n; n /= base, i++) *--s = (char)(digits[n % base]); + for (; i < F.precision; i++) *--s = '0'; + if (F.altForm) { *--s = (char)c; *--s = '0'; i += 2; } + if (F.sign) { *--s = F.sign; i++; } + break; + + case 'a' : { + unsigned char *a = va_arg(arg, unsigned char *); + char pre[4] = ""; + char post[32] = ""; + if (!a) { static char emsg[] = "<>"; s = emsg; i = sizeof(emsg)-1; } + else + { + s = mDNS_VACB; // Adjust s to point to the start of the buffer, not the end + if (F.altForm == 1) + { + #if(defined(MDNS_DEBUGMSGS)) + mDNSAddr *ip = (mDNSAddr*)a; + switch (ip->type) + { + case mDNSAddrType_IPv4: F.precision = 4; a = (unsigned char *)&ip->ip.v4; break; + case mDNSAddrType_IPv6: F.precision = 16; a = (unsigned char *)&ip->ip.v6; break; + default: F.precision = 0; break; + } + #else + F.precision = 0; // mDNSEmbeddedAPI.h not included so no mDNSAddr support + #endif + } + else if (F.altForm == 2) + { + #ifdef AF_INET + const struct sockaddr *sa; + unsigned char *port; + sa = (const struct sockaddr*)a; + switch (sa->sa_family) + { + case AF_INET: F.precision = 4; a = (unsigned char*)&((const struct sockaddr_in *)a)->sin_addr; + port = (unsigned char*)&((const struct sockaddr_in *)sa)->sin_port; + DebugSNPrintF(post, sizeof(post), ":%d", (port[0] << 8) | port[1]); break; + #ifdef AF_INET6 + case AF_INET6: F.precision = 16; a = (unsigned char*)&((const struct sockaddr_in6 *)a)->sin6_addr; + pre[0] = '['; pre[1] = '\0'; + port = (unsigned char*)&((const struct sockaddr_in6 *)sa)->sin6_port; + DebugSNPrintF(post, sizeof(post), "%%%d]:%d", + (int)((const struct sockaddr_in6 *)sa)->sin6_scope_id, + (port[0] << 8) | port[1]); break; + #endif + default: F.precision = 0; break; + } + #else + F.precision = 0; // socket interfaces not included so no sockaddr support + #endif + } + switch (F.precision) + { + case 4: i = DebugSNPrintF(mDNS_VACB, sizeof(mDNS_VACB), "%d.%d.%d.%d%s", + a[0], a[1], a[2], a[3], post); break; + case 6: i = DebugSNPrintF(mDNS_VACB, sizeof(mDNS_VACB), "%02X:%02X:%02X:%02X:%02X:%02X", + a[0], a[1], a[2], a[3], a[4], a[5]); break; + case 8: i = DebugSNPrintF(mDNS_VACB, sizeof(mDNS_VACB), "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", + a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]); break; + case 16: i = DebugSNPrintF(mDNS_VACB, sizeof(mDNS_VACB), + "%s%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X%s", + pre, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], + a[9], a[10], a[11], a[12], a[13], a[14], a[15], post); break; + default: i = DebugSNPrintF(mDNS_VACB, sizeof(mDNS_VACB), "%s", "<< ERROR: Must specify address size " + "(i.e. %.4a=IPv4, %.6a=Ethernet, %.8a=Fibre Channel %.16a=IPv6) >>"); break; + } + } + } + break; + + case 'U' : { + unsigned char *a = va_arg(arg, unsigned char *); + if (!a) { static char emsg[] = "<>"; s = emsg; i = sizeof(emsg)-1; } + else + { + s = mDNS_VACB; // Adjust s to point to the start of the buffer, not the end + i = DebugSNPrintF(mDNS_VACB, sizeof(mDNS_VACB), "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + *((uint32_t*) &a[0]), *((uint16_t*) &a[4]), *((uint16_t*) &a[6]), + a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15]); break; + } + } + break; + + case 'c' : *--s = (char)va_arg(arg, int); i = 1; break; + + case 'C' : if (F.lSize) n = va_arg(arg, unsigned long); + else n = va_arg(arg, unsigned int); + if (F.hSize) n = (unsigned short) n; + c = (int)( n & 0xFF); *--s = (char)(DebugIsPrint(c) ? c : '^'); + c = (int)((n >> 8) & 0xFF); *--s = (char)(DebugIsPrint(c) ? c : '^'); + c = (int)((n >> 16) & 0xFF); *--s = (char)(DebugIsPrint(c) ? c : '^'); + c = (int)((n >> 24) & 0xFF); *--s = (char)(DebugIsPrint(c) ? c : '^'); + i = 4; + break; + + case 's' : s = va_arg(arg, char *); + if (!s) { static char emsg[] = "<>"; s = emsg; i = sizeof(emsg)-1; } + else switch (F.altForm) + { + case 0: i=0; + if (F.havePrecision) // C string + { + while((i < F.precision) && s[i]) i++; + // Make sure we don't truncate in the middle of a UTF-8 character. + // If the last character is part of a multi-byte UTF-8 character, back up to the start of it. + j=0; + while((i > 0) && ((c = s[i-1]) & 0x80)) { j++; i--; if((c & 0xC0) != 0x80) break; } + // If the actual count of UTF-8 characters matches the encoded UTF-8 count, add it back. + if((j > 1) && (j <= 6)) + { + int test = (0xFF << (8-j)) & 0xFF; + int mask = test | (1 << ((8-j)-1)); + if((c & mask) == test) i += j; + } + } + else + while(s[i]) i++; + break; + case 1: i = (unsigned char) *s++; break; // Pascal string + case 2: { // DNS label-sequence name + unsigned char *a = (unsigned char *)s; + s = mDNS_VACB; // Adjust s to point to the start of the buffer, not the end + if (*a == 0) *s++ = '.'; // Special case for root DNS name + while (*a) + { + if (*a > 63) { s += DebugSNPrintF(s, mDNS_VACB_Remain(s), "<>", *a); break; } + if (s + *a >= &mDNS_VACB[254]) { s += DebugSNPrintF(s, mDNS_VACB_Remain(s), "<>"); break; } + s += DebugSNPrintF(s, mDNS_VACB_Remain(s), "%#s.", a); + a += 1 + *a; + } + i = (size_t)(s - mDNS_VACB); + s = mDNS_VACB; // Reset s back to the start of the buffer + break; + } + } + if (F.havePrecision && i > F.precision) // Make sure we don't truncate in the middle of a UTF-8 character + { i = F.precision; while (i>0 && (s[i] & 0xC0) == 0x80) i--; } + break; + + case 'S': { // UTF-16 string + unsigned char *a = va_arg(arg, unsigned char *); + uint16_t *u = (uint16_t*)a; + if (!u) { static char emsg[] = "<>"; s = emsg; i = sizeof(emsg)-1; } + if ((!F.havePrecision || F.precision)) + { + if ((a[0] == 0xFE) && (a[1] == 0xFF)) { F.altForm = 1; u += 1; a += 2; F.precision--; } // Big Endian + else if ((a[0] == 0xFF) && (a[1] == 0xFE)) { F.altForm = 2; u += 1; a += 2; F.precision--; } // Little Endian + } + s = mDNS_VACB; // Adjust s to point to the start of the buffer, not the end + switch (F.altForm) + { + case 0: while ((!F.havePrecision || (i < F.precision)) && u[i] && mDNS_VACB_Remain(s)) // Host Endian + { c = u[i]; *s++ = (char)(DebugIsPrint(c) ? c : '^'); i++; } + break; + case 1: while ((!F.havePrecision || (i < F.precision)) && u[i] && mDNS_VACB_Remain(s)) // Big Endian + { c = ((a[0] << 8) | a[1]) & 0xFF; *s++ = (char)(DebugIsPrint(c) ? c : '^'); i++; a += 2; } + break; + case 2: while ((!F.havePrecision || (i < F.precision)) && u[i] && mDNS_VACB_Remain(s)) // Little Endian + { c = ((a[1] << 8) | a[0]) & 0xFF; *s++ = (char)(DebugIsPrint(c) ? c : '^'); i++; a += 2; } + break; + } + } + s = mDNS_VACB; // Reset s back to the start of the buffer + break; + + #if TARGET_OS_MAC + case '@': { // Cocoa/CoreFoundation object + CFTypeRef cfObj; + CFStringRef cfStr; + cfObj = (CFTypeRef) va_arg(arg, void *); + cfStr = (CFGetTypeID(cfObj) == CFStringGetTypeID()) ? (CFStringRef)CFRetain(cfObj) : CFCopyDescription(cfObj); + s = mDNS_VACB; // Adjust s to point to the start of the buffer, not the end + if (cfStr) + { + CFRange range; + CFIndex m; + range = CFRangeMake(0, CFStringGetLength(cfStr)); + m = 0; + CFStringGetBytes(cfStr, range, kCFStringEncodingUTF8, '^', false, (UInt8*)mDNS_VACB, (CFIndex)sizeof(mDNS_VACB), &m); + CFRelease(cfStr); + i = (size_t) m; + } + else + { + i = DebugSNPrintF(mDNS_VACB, sizeof(mDNS_VACB), "%s", "ERROR: " ); + } + } + if (F.havePrecision && i > F.precision) // Make sure we don't truncate in the middle of a UTF-8 character + { i = F.precision; while (i>0 && (s[i] & 0xC0) == 0x80) i--; } + break; + #endif + + case 'm' : { // Error Message + long err; + if (F.lSize) err = va_arg(arg, long); + else err = va_arg(arg, int); + if (F.hSize) err = (short)err; + DebugGetErrorString(err, mDNS_VACB, sizeof(mDNS_VACB)); + s = mDNS_VACB; // Adjust s to point to the start of the buffer, not the end + for(i=0;s[i];i++) {} + } + break; + + case 'H' : { // Hex Dump + void *a = va_arg(arg, void *); + size_t size = (size_t)va_arg(arg, int); + size_t max = (size_t)va_arg(arg, int); + DebugFlags flags = + kDebugFlagsNoAddress | kDebugFlagsNoOffset | kDebugFlagsNoNewLine | + kDebugFlags8BitSeparator | kDebugFlagsNo32BitSeparator | + kDebugFlagsNo16ByteHexPad | kDebugFlagsNoByteCount; + if (F.altForm == 0) flags |= kDebugFlagsNoASCII; + size = (max < size) ? max : size; + s = mDNS_VACB; // Adjust s to point to the start of the buffer, not the end + i = DebugHexDump(kDebugLevelMax, 0, NULL, 0, 0, NULL, 0, a, a, size, flags, mDNS_VACB, sizeof(mDNS_VACB)); + } + break; + + case 'v' : { // Version + uint32_t version; + version = va_arg(arg, unsigned int); + DebugNumVersionToString(version, mDNS_VACB); + s = mDNS_VACB; // Adjust s to point to the start of the buffer, not the end + for(i=0;s[i];i++) {} + } + break; + + case 'n' : s = va_arg(arg, char *); + if (F.hSize) * (short *) s = (short)nwritten; + else if (F.lSize) * (long *) s = (long)nwritten; + else * (int *) s = (int)nwritten; + continue; + + default: s = mDNS_VACB; + i = DebugSNPrintF(mDNS_VACB, sizeof(mDNS_VACB), "<>", c); + + case '%' : *sbuffer++ = (char)c; + if (++nwritten >= buflen) goto exit; + break; + } + + if (i < F.fieldWidth && !F.leftJustify) // Pad on the left + do { + *sbuffer++ = ' '; + if (++nwritten >= buflen) goto exit; + } while (i < --F.fieldWidth); + + if (i > buflen - nwritten) // Make sure we don't truncate in the middle of a UTF-8 character + { i = buflen - nwritten; while (i>0 && (s[i] & 0xC0) == 0x80) i--; } + for (j=0; j= buflen) goto exit; + + for (; i < F.fieldWidth; i++) // Pad on the right + { + *sbuffer++ = ' '; + if (++nwritten >= buflen) goto exit; + } + } + } + exit: + *sbuffer++ = 0; + return(nwritten); + } + +//=========================================================================================================================== +// DebugGetErrorString +//=========================================================================================================================== + +DEBUG_EXPORT const char * DebugGetErrorString( int_least32_t inErrorCode, char *inBuffer, size_t inBufferSize ) +{ + const char * s; + char * dst; + char * end; +#if( TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE ) + char buffer[ 256 ]; +#endif + + switch( inErrorCode ) + { + #define CaseErrorString( X, STR ) case X: s = STR; break + #define CaseErrorStringify( X ) case X: s = # X; break + #define CaseErrorStringifyHardCode( VALUE, X ) case VALUE: s = # X; break + + // General Errors + + CaseErrorString( 0, "no error" ); + CaseErrorString( 1, "in-progress/waiting" ); + CaseErrorString( -1, "catch-all unknown error" ); + + // ACP Errors + + CaseErrorStringifyHardCode( -2, kACPBadRequestErr ); + CaseErrorStringifyHardCode( -3, kACPNoMemoryErr ); + CaseErrorStringifyHardCode( -4, kACPBadParamErr ); + CaseErrorStringifyHardCode( -5, kACPNotFoundErr ); + CaseErrorStringifyHardCode( -6, kACPBadChecksumErr ); + CaseErrorStringifyHardCode( -7, kACPCommandNotHandledErr ); + CaseErrorStringifyHardCode( -8, kACPNetworkErr ); + CaseErrorStringifyHardCode( -9, kACPDuplicateCommandHandlerErr ); + CaseErrorStringifyHardCode( -10, kACPUnknownPropertyErr ); + CaseErrorStringifyHardCode( -11, kACPImmutablePropertyErr ); + CaseErrorStringifyHardCode( -12, kACPBadPropertyValueErr ); + CaseErrorStringifyHardCode( -13, kACPNoResourcesErr ); + CaseErrorStringifyHardCode( -14, kACPBadOptionErr ); + CaseErrorStringifyHardCode( -15, kACPBadSizeErr ); + CaseErrorStringifyHardCode( -16, kACPBadPasswordErr ); + CaseErrorStringifyHardCode( -17, kACPNotInitializedErr ); + CaseErrorStringifyHardCode( -18, kACPNonReadablePropertyErr ); + CaseErrorStringifyHardCode( -19, kACPBadVersionErr ); + CaseErrorStringifyHardCode( -20, kACPBadSignatureErr ); + CaseErrorStringifyHardCode( -21, kACPBadIndexErr ); + CaseErrorStringifyHardCode( -22, kACPUnsupportedErr ); + CaseErrorStringifyHardCode( -23, kACPInUseErr ); + CaseErrorStringifyHardCode( -24, kACPParamCountErr ); + CaseErrorStringifyHardCode( -25, kACPIDErr ); + CaseErrorStringifyHardCode( -26, kACPFormatErr ); + CaseErrorStringifyHardCode( -27, kACPUnknownUserErr ); + CaseErrorStringifyHardCode( -28, kACPAccessDeniedErr ); + CaseErrorStringifyHardCode( -29, kACPIncorrectFWErr ); + + // Common Services Errors + + CaseErrorStringify( kUnknownErr ); + CaseErrorStringify( kOptionErr ); + CaseErrorStringify( kSelectorErr ); + CaseErrorStringify( kExecutionStateErr ); + CaseErrorStringify( kPathErr ); + CaseErrorStringify( kParamErr ); + CaseErrorStringify( kParamCountErr ); + CaseErrorStringify( kCommandErr ); + CaseErrorStringify( kIDErr ); + CaseErrorStringify( kStateErr ); + CaseErrorStringify( kRangeErr ); + CaseErrorStringify( kRequestErr ); + CaseErrorStringify( kResponseErr ); + CaseErrorStringify( kChecksumErr ); + CaseErrorStringify( kNotHandledErr ); + CaseErrorStringify( kVersionErr ); + CaseErrorStringify( kSignatureErr ); + CaseErrorStringify( kFormatErr ); + CaseErrorStringify( kNotInitializedErr ); + CaseErrorStringify( kAlreadyInitializedErr ); + CaseErrorStringify( kNotInUseErr ); + CaseErrorStringify( kInUseErr ); + CaseErrorStringify( kTimeoutErr ); + CaseErrorStringify( kCanceledErr ); + CaseErrorStringify( kAlreadyCanceledErr ); + CaseErrorStringify( kCannotCancelErr ); + CaseErrorStringify( kDeletedErr ); + CaseErrorStringify( kNotFoundErr ); + CaseErrorStringify( kNoMemoryErr ); + CaseErrorStringify( kNoResourcesErr ); + CaseErrorStringify( kDuplicateErr ); + CaseErrorStringify( kImmutableErr ); + CaseErrorStringify( kUnsupportedDataErr ); + CaseErrorStringify( kIntegrityErr ); + CaseErrorStringify( kIncompatibleErr ); + CaseErrorStringify( kUnsupportedErr ); + CaseErrorStringify( kUnexpectedErr ); + CaseErrorStringify( kValueErr ); + CaseErrorStringify( kNotReadableErr ); + CaseErrorStringify( kNotWritableErr ); + CaseErrorStringify( kBadReferenceErr ); + CaseErrorStringify( kFlagErr ); + CaseErrorStringify( kMalformedErr ); + CaseErrorStringify( kSizeErr ); + CaseErrorStringify( kNameErr ); + CaseErrorStringify( kNotReadyErr ); + CaseErrorStringify( kReadErr ); + CaseErrorStringify( kWriteErr ); + CaseErrorStringify( kMismatchErr ); + CaseErrorStringify( kDateErr ); + CaseErrorStringify( kUnderrunErr ); + CaseErrorStringify( kOverrunErr ); + CaseErrorStringify( kEndingErr ); + CaseErrorStringify( kConnectionErr ); + CaseErrorStringify( kAuthenticationErr ); + CaseErrorStringify( kOpenErr ); + CaseErrorStringify( kTypeErr ); + CaseErrorStringify( kSkipErr ); + CaseErrorStringify( kNoAckErr ); + CaseErrorStringify( kCollisionErr ); + CaseErrorStringify( kBackoffErr ); + CaseErrorStringify( kNoAddressAckErr ); + CaseErrorStringify( kBusyErr ); + CaseErrorStringify( kNoSpaceErr ); + + // mDNS/DNS-SD Errors + + CaseErrorStringifyHardCode( -65537, mStatus_UnknownErr ); + CaseErrorStringifyHardCode( -65538, mStatus_NoSuchNameErr ); + CaseErrorStringifyHardCode( -65539, mStatus_NoMemoryErr ); + CaseErrorStringifyHardCode( -65540, mStatus_BadParamErr ); + CaseErrorStringifyHardCode( -65541, mStatus_BadReferenceErr ); + CaseErrorStringifyHardCode( -65542, mStatus_BadStateErr ); + CaseErrorStringifyHardCode( -65543, mStatus_BadFlagsErr ); + CaseErrorStringifyHardCode( -65544, mStatus_UnsupportedErr ); + CaseErrorStringifyHardCode( -65545, mStatus_NotInitializedErr ); + CaseErrorStringifyHardCode( -65546, mStatus_NoCache ); + CaseErrorStringifyHardCode( -65547, mStatus_AlreadyRegistered ); + CaseErrorStringifyHardCode( -65548, mStatus_NameConflict ); + CaseErrorStringifyHardCode( -65549, mStatus_Invalid ); + CaseErrorStringifyHardCode( -65550, mStatus_GrowCache ); + CaseErrorStringifyHardCode( -65551, mStatus_BadInterfaceErr ); + CaseErrorStringifyHardCode( -65552, mStatus_Incompatible ); + CaseErrorStringifyHardCode( -65791, mStatus_ConfigChanged ); + CaseErrorStringifyHardCode( -65792, mStatus_MemFree ); + + // RSP Errors + + CaseErrorStringifyHardCode( -400000, kRSPUnknownErr ); + CaseErrorStringifyHardCode( -400050, kRSPParamErr ); + CaseErrorStringifyHardCode( -400108, kRSPNoMemoryErr ); + CaseErrorStringifyHardCode( -405246, kRSPRangeErr ); + CaseErrorStringifyHardCode( -409057, kRSPSizeErr ); + CaseErrorStringifyHardCode( -400200, kRSPHardwareErr ); + CaseErrorStringifyHardCode( -401712, kRSPTimeoutErr ); + CaseErrorStringifyHardCode( -402053, kRSPUnsupportedErr ); + CaseErrorStringifyHardCode( -402419, kRSPIDErr ); + CaseErrorStringifyHardCode( -403165, kRSPFlagErr ); + CaseErrorString( -200000, "kRSPControllerStatusBase - 0x50" ); + CaseErrorString( -200080, "kRSPCommandSucceededErr - 0x50" ); + CaseErrorString( -200001, "kRSPCommandFailedErr - 0x01" ); + CaseErrorString( -200051, "kRSPChecksumErr - 0x33" ); + CaseErrorString( -200132, "kRSPCommandTimeoutErr - 0x84" ); + CaseErrorString( -200034, "kRSPPasswordRequiredErr - 0x22 OBSOLETE" ); + CaseErrorString( -200128, "kRSPCanceledErr - 0x02 Async" ); + + // XML Errors + + CaseErrorStringifyHardCode( -100043, kXMLNotFoundErr ); + CaseErrorStringifyHardCode( -100050, kXMLParamErr ); + CaseErrorStringifyHardCode( -100108, kXMLNoMemoryErr ); + CaseErrorStringifyHardCode( -100206, kXMLFormatErr ); + CaseErrorStringifyHardCode( -100586, kXMLNoRootElementErr ); + CaseErrorStringifyHardCode( -101703, kXMLWrongDataTypeErr ); + CaseErrorStringifyHardCode( -101726, kXMLKeyErr ); + CaseErrorStringifyHardCode( -102053, kXMLUnsupportedErr ); + CaseErrorStringifyHardCode( -102063, kXMLMissingElementErr ); + CaseErrorStringifyHardCode( -103026, kXMLParseErr ); + CaseErrorStringifyHardCode( -103159, kXMLBadDataErr ); + CaseErrorStringifyHardCode( -103170, kXMLBadNameErr ); + CaseErrorStringifyHardCode( -105246, kXMLRangeErr ); + CaseErrorStringifyHardCode( -105251, kXMLUnknownElementErr ); + CaseErrorStringifyHardCode( -108739, kXMLMalformedInputErr ); + CaseErrorStringifyHardCode( -109057, kXMLBadSizeErr ); + CaseErrorStringifyHardCode( -101730, kXMLMissingChildElementErr ); + CaseErrorStringifyHardCode( -102107, kXMLMissingParentElementErr ); + CaseErrorStringifyHardCode( -130587, kXMLNonRootElementErr ); + CaseErrorStringifyHardCode( -102015, kXMLDateErr ); + + #if( __MACH__ ) + + // Mach Errors + + CaseErrorStringifyHardCode( 0x00002000, MACH_MSG_IPC_SPACE ); + CaseErrorStringifyHardCode( 0x00001000, MACH_MSG_VM_SPACE ); + CaseErrorStringifyHardCode( 0x00000800, MACH_MSG_IPC_KERNEL ); + CaseErrorStringifyHardCode( 0x00000400, MACH_MSG_VM_KERNEL ); + CaseErrorStringifyHardCode( 0x10000001, MACH_SEND_IN_PROGRESS ); + CaseErrorStringifyHardCode( 0x10000002, MACH_SEND_INVALID_DATA ); + CaseErrorStringifyHardCode( 0x10000003, MACH_SEND_INVALID_DEST ); + CaseErrorStringifyHardCode( 0x10000004, MACH_SEND_TIMED_OUT ); + CaseErrorStringifyHardCode( 0x10000007, MACH_SEND_INTERRUPTED ); + CaseErrorStringifyHardCode( 0x10000008, MACH_SEND_MSG_TOO_SMALL ); + CaseErrorStringifyHardCode( 0x10000009, MACH_SEND_INVALID_REPLY ); + CaseErrorStringifyHardCode( 0x1000000A, MACH_SEND_INVALID_RIGHT ); + CaseErrorStringifyHardCode( 0x1000000B, MACH_SEND_INVALID_NOTIFY ); + CaseErrorStringifyHardCode( 0x1000000C, MACH_SEND_INVALID_MEMORY ); + CaseErrorStringifyHardCode( 0x1000000D, MACH_SEND_NO_BUFFER ); + CaseErrorStringifyHardCode( 0x1000000E, MACH_SEND_TOO_LARGE ); + CaseErrorStringifyHardCode( 0x1000000F, MACH_SEND_INVALID_TYPE ); + CaseErrorStringifyHardCode( 0x10000010, MACH_SEND_INVALID_HEADER ); + CaseErrorStringifyHardCode( 0x10000011, MACH_SEND_INVALID_TRAILER ); + CaseErrorStringifyHardCode( 0x10000015, MACH_SEND_INVALID_RT_OOL_SIZE ); + CaseErrorStringifyHardCode( 0x10004001, MACH_RCV_IN_PROGRESS ); + CaseErrorStringifyHardCode( 0x10004002, MACH_RCV_INVALID_NAME ); + CaseErrorStringifyHardCode( 0x10004003, MACH_RCV_TIMED_OUT ); + CaseErrorStringifyHardCode( 0x10004004, MACH_RCV_TOO_LARGE ); + CaseErrorStringifyHardCode( 0x10004005, MACH_RCV_INTERRUPTED ); + CaseErrorStringifyHardCode( 0x10004006, MACH_RCV_PORT_CHANGED ); + CaseErrorStringifyHardCode( 0x10004007, MACH_RCV_INVALID_NOTIFY ); + CaseErrorStringifyHardCode( 0x10004008, MACH_RCV_INVALID_DATA ); + CaseErrorStringifyHardCode( 0x10004009, MACH_RCV_PORT_DIED ); + CaseErrorStringifyHardCode( 0x1000400A, MACH_RCV_IN_SET ); + CaseErrorStringifyHardCode( 0x1000400B, MACH_RCV_HEADER_ERROR ); + CaseErrorStringifyHardCode( 0x1000400C, MACH_RCV_BODY_ERROR ); + CaseErrorStringifyHardCode( 0x1000400D, MACH_RCV_INVALID_TYPE ); + CaseErrorStringifyHardCode( 0x1000400E, MACH_RCV_SCATTER_SMALL ); + CaseErrorStringifyHardCode( 0x1000400F, MACH_RCV_INVALID_TRAILER ); + CaseErrorStringifyHardCode( 0x10004011, MACH_RCV_IN_PROGRESS_TIMED ); + + // Mach OSReturn Errors + + CaseErrorStringifyHardCode( 0xDC000001, kOSReturnError ); + CaseErrorStringifyHardCode( 0xDC004001, kOSMetaClassInternal ); + CaseErrorStringifyHardCode( 0xDC004002, kOSMetaClassHasInstances ); + CaseErrorStringifyHardCode( 0xDC004003, kOSMetaClassNoInit ); + CaseErrorStringifyHardCode( 0xDC004004, kOSMetaClassNoTempData ); + CaseErrorStringifyHardCode( 0xDC004005, kOSMetaClassNoDicts ); + CaseErrorStringifyHardCode( 0xDC004006, kOSMetaClassNoKModSet ); + CaseErrorStringifyHardCode( 0xDC004007, kOSMetaClassNoInsKModSet ); + CaseErrorStringifyHardCode( 0xDC004008, kOSMetaClassNoSuper ); + CaseErrorStringifyHardCode( 0xDC004009, kOSMetaClassInstNoSuper ); + CaseErrorStringifyHardCode( 0xDC00400A, kOSMetaClassDuplicateClass ); + + // IOKit Errors + + CaseErrorStringifyHardCode( 0xE00002BC, kIOReturnError ); + CaseErrorStringifyHardCode( 0xE00002BD, kIOReturnNoMemory ); + CaseErrorStringifyHardCode( 0xE00002BE, kIOReturnNoResources ); + CaseErrorStringifyHardCode( 0xE00002BF, kIOReturnIPCError ); + CaseErrorStringifyHardCode( 0xE00002C0, kIOReturnNoDevice ); + CaseErrorStringifyHardCode( 0xE00002C1, kIOReturnNotPrivileged ); + CaseErrorStringifyHardCode( 0xE00002C2, kIOReturnBadArgument ); + CaseErrorStringifyHardCode( 0xE00002C3, kIOReturnLockedRead ); + CaseErrorStringifyHardCode( 0xE00002C4, kIOReturnLockedWrite ); + CaseErrorStringifyHardCode( 0xE00002C5, kIOReturnExclusiveAccess ); + CaseErrorStringifyHardCode( 0xE00002C6, kIOReturnBadMessageID ); + CaseErrorStringifyHardCode( 0xE00002C7, kIOReturnUnsupported ); + CaseErrorStringifyHardCode( 0xE00002C8, kIOReturnVMError ); + CaseErrorStringifyHardCode( 0xE00002C9, kIOReturnInternalError ); + CaseErrorStringifyHardCode( 0xE00002CA, kIOReturnIOError ); + CaseErrorStringifyHardCode( 0xE00002CC, kIOReturnCannotLock ); + CaseErrorStringifyHardCode( 0xE00002CD, kIOReturnNotOpen ); + CaseErrorStringifyHardCode( 0xE00002CE, kIOReturnNotReadable ); + CaseErrorStringifyHardCode( 0xE00002CF, kIOReturnNotWritable ); + CaseErrorStringifyHardCode( 0xE00002D0, kIOReturnNotAligned ); + CaseErrorStringifyHardCode( 0xE00002D1, kIOReturnBadMedia ); + CaseErrorStringifyHardCode( 0xE00002D2, kIOReturnStillOpen ); + CaseErrorStringifyHardCode( 0xE00002D3, kIOReturnRLDError ); + CaseErrorStringifyHardCode( 0xE00002D4, kIOReturnDMAError ); + CaseErrorStringifyHardCode( 0xE00002D5, kIOReturnBusy ); + CaseErrorStringifyHardCode( 0xE00002D6, kIOReturnTimeout ); + CaseErrorStringifyHardCode( 0xE00002D7, kIOReturnOffline ); + CaseErrorStringifyHardCode( 0xE00002D8, kIOReturnNotReady ); + CaseErrorStringifyHardCode( 0xE00002D9, kIOReturnNotAttached ); + CaseErrorStringifyHardCode( 0xE00002DA, kIOReturnNoChannels ); + CaseErrorStringifyHardCode( 0xE00002DB, kIOReturnNoSpace ); + CaseErrorStringifyHardCode( 0xE00002DD, kIOReturnPortExists ); + CaseErrorStringifyHardCode( 0xE00002DE, kIOReturnCannotWire ); + CaseErrorStringifyHardCode( 0xE00002DF, kIOReturnNoInterrupt ); + CaseErrorStringifyHardCode( 0xE00002E0, kIOReturnNoFrames ); + CaseErrorStringifyHardCode( 0xE00002E1, kIOReturnMessageTooLarge ); + CaseErrorStringifyHardCode( 0xE00002E2, kIOReturnNotPermitted ); + CaseErrorStringifyHardCode( 0xE00002E3, kIOReturnNoPower ); + CaseErrorStringifyHardCode( 0xE00002E4, kIOReturnNoMedia ); + CaseErrorStringifyHardCode( 0xE00002E5, kIOReturnUnformattedMedia ); + CaseErrorStringifyHardCode( 0xE00002E6, kIOReturnUnsupportedMode ); + CaseErrorStringifyHardCode( 0xE00002E7, kIOReturnUnderrun ); + CaseErrorStringifyHardCode( 0xE00002E8, kIOReturnOverrun ); + CaseErrorStringifyHardCode( 0xE00002E9, kIOReturnDeviceError ); + CaseErrorStringifyHardCode( 0xE00002EA, kIOReturnNoCompletion ); + CaseErrorStringifyHardCode( 0xE00002EB, kIOReturnAborted ); + CaseErrorStringifyHardCode( 0xE00002EC, kIOReturnNoBandwidth ); + CaseErrorStringifyHardCode( 0xE00002ED, kIOReturnNotResponding ); + CaseErrorStringifyHardCode( 0xE00002EE, kIOReturnIsoTooOld ); + CaseErrorStringifyHardCode( 0xE00002EF, kIOReturnIsoTooNew ); + CaseErrorStringifyHardCode( 0xE00002F0, kIOReturnNotFound ); + CaseErrorStringifyHardCode( 0xE0000001, kIOReturnInvalid ); + + // IOKit FireWire Errors + + CaseErrorStringifyHardCode( 0xE0008010, kIOFireWireResponseBase ); + CaseErrorStringifyHardCode( 0xE0008020, kIOFireWireBusReset ); + CaseErrorStringifyHardCode( 0xE0008001, kIOConfigNoEntry ); + CaseErrorStringifyHardCode( 0xE0008002, kIOFireWirePending ); + CaseErrorStringifyHardCode( 0xE0008003, kIOFireWireLastDCLToken ); + CaseErrorStringifyHardCode( 0xE0008004, kIOFireWireConfigROMInvalid ); + CaseErrorStringifyHardCode( 0xE0008005, kIOFireWireAlreadyRegistered ); + CaseErrorStringifyHardCode( 0xE0008006, kIOFireWireMultipleTalkers ); + CaseErrorStringifyHardCode( 0xE0008007, kIOFireWireChannelActive ); + CaseErrorStringifyHardCode( 0xE0008008, kIOFireWireNoListenerOrTalker ); + CaseErrorStringifyHardCode( 0xE0008009, kIOFireWireNoChannels ); + CaseErrorStringifyHardCode( 0xE000800A, kIOFireWireChannelNotAvailable ); + CaseErrorStringifyHardCode( 0xE000800B, kIOFireWireSeparateBus ); + CaseErrorStringifyHardCode( 0xE000800C, kIOFireWireBadSelfIDs ); + CaseErrorStringifyHardCode( 0xE000800D, kIOFireWireLowCableVoltage ); + CaseErrorStringifyHardCode( 0xE000800E, kIOFireWireInsufficientPower ); + CaseErrorStringifyHardCode( 0xE000800F, kIOFireWireOutOfTLabels ); + CaseErrorStringifyHardCode( 0xE0008101, kIOFireWireBogusDCLProgram ); + CaseErrorStringifyHardCode( 0xE0008102, kIOFireWireTalkingAndListening ); + CaseErrorStringifyHardCode( 0xE0008103, kIOFireWireHardwareSlept ); + CaseErrorStringifyHardCode( 0xE00087D0, kIOFWMessageServiceIsRequestingClose ); + CaseErrorStringifyHardCode( 0xE00087D1, kIOFWMessagePowerStateChanged ); + CaseErrorStringifyHardCode( 0xE00087D2, kIOFWMessageTopologyChanged ); + + // IOKit USB Errors + + CaseErrorStringifyHardCode( 0xE0004061, kIOUSBUnknownPipeErr ); + CaseErrorStringifyHardCode( 0xE0004060, kIOUSBTooManyPipesErr ); + CaseErrorStringifyHardCode( 0xE000405F, kIOUSBNoAsyncPortErr ); + CaseErrorStringifyHardCode( 0xE000405E, kIOUSBNotEnoughPipesErr ); + CaseErrorStringifyHardCode( 0xE000405D, kIOUSBNotEnoughPowerErr ); + CaseErrorStringifyHardCode( 0xE0004057, kIOUSBEndpointNotFound ); + CaseErrorStringifyHardCode( 0xE0004056, kIOUSBConfigNotFound ); + CaseErrorStringifyHardCode( 0xE0004051, kIOUSBTransactionTimeout ); + CaseErrorStringifyHardCode( 0xE0004050, kIOUSBTransactionReturned ); + CaseErrorStringifyHardCode( 0xE000404F, kIOUSBPipeStalled ); + CaseErrorStringifyHardCode( 0xE000404E, kIOUSBInterfaceNotFound ); + CaseErrorStringifyHardCode( 0xE000404D, kIOUSBLowLatencyBufferNotPreviouslyAllocated ); + CaseErrorStringifyHardCode( 0xE000404C, kIOUSBLowLatencyFrameListNotPreviouslyAllocated ); + CaseErrorStringifyHardCode( 0xE000404B, kIOUSBHighSpeedSplitError ); + CaseErrorStringifyHardCode( 0xE0004010, kIOUSBLinkErr ); + CaseErrorStringifyHardCode( 0xE000400F, kIOUSBNotSent2Err ); + CaseErrorStringifyHardCode( 0xE000400E, kIOUSBNotSent1Err ); + CaseErrorStringifyHardCode( 0xE000400D, kIOUSBBufferUnderrunErr ); + CaseErrorStringifyHardCode( 0xE000400C, kIOUSBBufferOverrunErr ); + CaseErrorStringifyHardCode( 0xE000400B, kIOUSBReserved2Err ); + CaseErrorStringifyHardCode( 0xE000400A, kIOUSBReserved1Err ); + CaseErrorStringifyHardCode( 0xE0004007, kIOUSBWrongPIDErr ); + CaseErrorStringifyHardCode( 0xE0004006, kIOUSBPIDCheckErr ); + CaseErrorStringifyHardCode( 0xE0004003, kIOUSBDataToggleErr ); + CaseErrorStringifyHardCode( 0xE0004002, kIOUSBBitstufErr ); + CaseErrorStringifyHardCode( 0xE0004001, kIOUSBCRCErr ); + + #endif // __MACH__ + + // Other Errors + + default: + s = NULL; + #if( TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE ) + if( inBuffer && ( inBufferSize > 0 ) ) + { + DWORD n; + + n = FormatMessageA( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, (DWORD) inErrorCode, + MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), buffer, sizeof( buffer ), NULL ); + if( n > 0 ) + { + // Remove any trailing CR's or LF's since some messages have them. + + while( ( n > 0 ) && isspace( ( (unsigned char *) buffer )[ n - 1 ] ) ) + { + buffer[ --n ] = '\0'; + } + s = buffer; + } + } + #endif + + if( !s ) + { + #if( !TARGET_API_MAC_OSX_KERNEL && !TARGET_OS_WINDOWS_CE ) + s = strerror( inErrorCode ); + #endif + if( !s ) + { + s = ""; + } + } + break; + } + + // Copy the string to the output buffer. If no buffer is supplied or it is empty, return an empty string. + + if( inBuffer && ( inBufferSize > 0 ) ) + { + dst = inBuffer; + end = dst + ( inBufferSize - 1 ); + while( ( ( end - dst ) > 0 ) && ( *s != '\0' ) ) + { + *dst++ = *s++; + } + *dst = '\0'; + s = inBuffer; + } + return( s ); +} + +//=========================================================================================================================== +// DebugHexDump +//=========================================================================================================================== + +DEBUG_EXPORT size_t + DebugHexDump( + DebugLevel inLevel, + int inIndent, + const char * inLabel, + size_t inLabelSize, + int inLabelMinWidth, + const char * inType, + size_t inTypeSize, + const void * inDataStart, + const void * inData, + size_t inDataSize, + DebugFlags inFlags, + char * outBuffer, + size_t inBufferSize ) +{ + static const char kHexChars[] = "0123456789ABCDEF"; + const uint8_t * start; + const uint8_t * src; + char * dst; + char * end; + size_t n; + int offset; + int width; + const char * newline; + char separator[ 8 ]; + char * s; + + DEBUG_UNUSED( inType ); + DEBUG_UNUSED( inTypeSize ); + + // Set up the function-wide variables. + + if( inLabelSize == kSizeCString ) + { + inLabelSize = strlen( inLabel ); + } + start = (const uint8_t *) inData; + src = start; + dst = outBuffer; + end = dst + inBufferSize; + offset = (int)( (intptr_t) inData - (intptr_t) inDataStart ); + width = ( (int) inLabelSize > inLabelMinWidth ) ? (int) inLabelSize : inLabelMinWidth; + newline = ( inFlags & kDebugFlagsNoNewLine ) ? "" : "\n"; + + // Set up the separator string. This is used to insert spaces on subsequent "lines" when not using newlines. + + s = separator; + if( inFlags & kDebugFlagsNoNewLine ) + { + if( inFlags & kDebugFlags8BitSeparator ) + { + *s++ = ' '; + } + if( inFlags & kDebugFlags16BitSeparator ) + { + *s++ = ' '; + } + if( !( inFlags & kDebugFlagsNo32BitSeparator ) ) + { + *s++ = ' '; + } + check( ( (size_t)( s - separator ) ) < sizeof( separator ) ); + } + *s = '\0'; + + for( ;; ) + { + char prefixString[ 32 ]; + char hexString[ 64 ]; + char asciiString[ 32 ]; + char byteCountString[ 32 ]; + int c; + size_t chunkSize; + size_t i; + + // If this is a label-only item (i.e. no data), print the label (accounting for prefix string spacing) and exit. + + if( inDataSize == 0 ) + { + if( inLabel && ( inLabelSize > 0 ) ) + { + width = 0; + if( !( inFlags & kDebugFlagsNoAddress ) ) + { + width += 8; // "00000000" + if( !( inFlags & kDebugFlagsNoOffset ) ) + { + width += 1; // "+" + } + } + if( inFlags & kDebugFlags32BitOffset ) + { + width += 8; // "00000000" + } + else if( !( inFlags & kDebugFlagsNoOffset ) ) + { + width += 4; // "0000" + } + + if( outBuffer ) + { + dst += DebugSNPrintF( dst, (size_t)( end - dst ), "%*s" "%-*.*s" "%.*s" "%s", + width, "", + ( width > 0 ) ? ": " : "", + width, (int) inLabelSize, inLabel, + newline ); + } + else + { + dst += DebugPrintF( inLevel, "%*s" "%-*.*s" "%.*s" "%s", + width, "", + ( width > 0 ) ? ": " : "", + width, (int) inLabelSize, inLabel, + newline ); + } + } + break; + } + + // Build the prefix string. It will be in one of the following formats: + // + // 1) "00000000+0000[0000]" (address and offset) + // 2) "00000000" (address only) + // 3) "0000[0000]" (offset only) + // 4) "" (no address or offset) + // + // Note: If we're printing multiple "lines", but not printing newlines, a space is used to separate. + + s = prefixString; + if( !( inFlags & kDebugFlagsNoAddress ) ) + { + *s++ = kHexChars[ ( ( (uintptr_t) src ) >> 28 ) & 0xF ]; + *s++ = kHexChars[ ( ( (uintptr_t) src ) >> 24 ) & 0xF ]; + *s++ = kHexChars[ ( ( (uintptr_t) src ) >> 20 ) & 0xF ]; + *s++ = kHexChars[ ( ( (uintptr_t) src ) >> 16 ) & 0xF ]; + *s++ = kHexChars[ ( ( (uintptr_t) src ) >> 12 ) & 0xF ]; + *s++ = kHexChars[ ( ( (uintptr_t) src ) >> 8 ) & 0xF ]; + *s++ = kHexChars[ ( ( (uintptr_t) src ) >> 4 ) & 0xF ]; + *s++ = kHexChars[ ( (uintptr_t) src ) & 0xF ]; + + if( !( inFlags & kDebugFlagsNoOffset ) ) + { + *s++ = '+'; + } + } + if( !( inFlags & kDebugFlagsNoOffset ) ) + { + if( inFlags & kDebugFlags32BitOffset ) + { + *s++ = kHexChars[ ( offset >> 28 ) & 0xF ]; + *s++ = kHexChars[ ( offset >> 24 ) & 0xF ]; + *s++ = kHexChars[ ( offset >> 20 ) & 0xF ]; + *s++ = kHexChars[ ( offset >> 16 ) & 0xF ]; + } + *s++ = kHexChars[ ( offset >> 12 ) & 0xF ]; + *s++ = kHexChars[ ( offset >> 8 ) & 0xF ]; + *s++ = kHexChars[ ( offset >> 4 ) & 0xF ]; + *s++ = kHexChars[ offset & 0xF ]; + } + if( s != prefixString ) + { + *s++ = ':'; + *s++ = ' '; + } + check( ( (size_t)( s - prefixString ) ) < sizeof( prefixString ) ); + *s = '\0'; + + // Build a hex string with a optional spaces after every 1, 2, and/or 4 bytes to make it easier to read. + // Optionally pads the hex string with space to fill the full 16 byte range (so it lines up). + + s = hexString; + chunkSize = ( inDataSize < 16 ) ? inDataSize : 16; + n = ( inFlags & kDebugFlagsNo16ByteHexPad ) ? chunkSize : 16; + for( i = 0; i < n; ++i ) + { + if( ( inFlags & kDebugFlags8BitSeparator ) && ( i > 0 ) ) + { + *s++ = ' '; + } + if( ( inFlags & kDebugFlags16BitSeparator ) && ( i > 0 ) && ( ( i % 2 ) == 0 ) ) + { + *s++ = ' '; + } + if( !( inFlags & kDebugFlagsNo32BitSeparator ) && ( i > 0 ) && ( ( i % 4 ) == 0 ) ) + { + *s++ = ' '; + } + if( i < chunkSize ) + { + *s++ = kHexChars[ src[ i ] >> 4 ]; + *s++ = kHexChars[ src[ i ] & 0xF ]; + } + else + { + *s++ = ' '; + *s++ = ' '; + } + } + check( ( (size_t)( s - hexString ) ) < sizeof( hexString ) ); + *s = '\0'; + + // Build a string with the ASCII version of the data (replaces non-printable characters with '^'). + // Optionally pads the string with '`' to fill the full 16 byte range (so it lines up). + + s = asciiString; + if( !( inFlags & kDebugFlagsNoASCII ) ) + { + *s++ = ' '; + *s++ = '|'; + for( i = 0; i < n; ++i ) + { + if( i < chunkSize ) + { + c = src[ i ]; + if( !DebugIsPrint( c ) ) + { + c = '^'; + } + } + else + { + c = '`'; + } + *s++ = (char) c; + } + *s++ = '|'; + check( ( (size_t)( s - asciiString ) ) < sizeof( asciiString ) ); + } + *s = '\0'; + + // Build a string indicating how bytes are in the hex dump. Only printed on the first line. + + s = byteCountString; + if( !( inFlags & kDebugFlagsNoByteCount ) ) + { + if( src == start ) + { + s += DebugSNPrintF( s, sizeof( byteCountString ), " (%d bytes)", (int) inDataSize ); + } + } + check( ( (size_t)( s - byteCountString ) ) < sizeof( byteCountString ) ); + *s = '\0'; + + // Build the entire line from all the pieces we've previously built. + + if( outBuffer ) + { + if( src == start ) + { + dst += DebugSNPrintF( dst, (size_t)( end - dst ), + "%*s" // Indention + "%s" // Separator (only if needed) + "%s" // Prefix + "%-*.*s" // Label + "%s" // Separator + "%s" // Hex + "%s" // ASCII + "%s" // Byte Count + "%s", // Newline + inIndent, "", + ( src != start ) ? separator : "", + prefixString, + width, (int) inLabelSize, inLabel ? inLabel : "", + ( width > 0 ) ? " " : "", + hexString, + asciiString, + byteCountString, + newline ); + } + else + { + dst += DebugSNPrintF( dst, (size_t)( end - dst ), + "%*s" // Indention + "%s" // Separator (only if needed) + "%s" // Prefix + "%*s" // Label Spacing + "%s" // Separator + "%s" // Hex + "%s" // ASCII + "%s" // Byte Count + "%s", // Newline + inIndent, "", + ( src != start ) ? separator : "", + prefixString, + width, "", + ( width > 0 ) ? " " : "", + hexString, + asciiString, + byteCountString, + newline ); + } + } + else + { + if( src == start ) + { + dst += DebugPrintF( inLevel, + "%*s" // Indention + "%s" // Separator (only if needed) + "%s" // Prefix + "%-*.*s" // Label + "%s" // Separator + "%s" // Hex + "%s" // ASCII + "%s" // Byte Count + "%s", // Newline + inIndent, "", + ( src != start ) ? separator : "", + prefixString, + width, (int) inLabelSize, inLabel, + ( width > 0 ) ? " " : "", + hexString, + asciiString, + byteCountString, + newline ); + } + else + { + dst += DebugPrintF( inLevel, + "%*s" // Indention + "%s" // Separator (only if needed) + "%s" // Prefix + "%*s" // Label Spacing + "%s" // Separator + "%s" // Hex + "%s" // ASCII + "%s" // Byte Count + "%s", // Newline + inIndent, "", + ( src != start ) ? separator : "", + prefixString, + width, "", + ( width > 0 ) ? " " : "", + hexString, + asciiString, + byteCountString, + newline ); + } + } + + // Move to the next chunk. Exit if there is no more data. + + offset += (int) chunkSize; + src += chunkSize; + inDataSize -= chunkSize; + if( inDataSize == 0 ) + { + break; + } + } + + // Note: The "dst - outBuffer" size calculation works even if "outBuffer" is NULL because it's all relative. + + return( (size_t)( dst - outBuffer ) ); +} + +//=========================================================================================================================== +// DebugNumVersionToString +//=========================================================================================================================== + +static char * DebugNumVersionToString( uint32_t inVersion, char *inString ) +{ + char * s; + uint8_t majorRev; + uint8_t minor; + uint8_t bugFix; + uint8_t stage; + uint8_t revision; + + check( inString ); + + majorRev = (uint8_t)( ( inVersion >> 24 ) & 0xFF ); + minor = (uint8_t)( ( inVersion >> 20 ) & 0x0F ); + bugFix = (uint8_t)( ( inVersion >> 16 ) & 0x0F ); + stage = (uint8_t)( ( inVersion >> 8 ) & 0xFF ); + revision = (uint8_t)( inVersion & 0xFF ); + + // Convert the major, minor, and bugfix numbers. + + s = inString; + s += sprintf( s, "%u", majorRev ); + s += sprintf( s, ".%u", minor ); + if( bugFix != 0 ) + { + s += sprintf( s, ".%u", bugFix ); + } + + // Convert the version stage and non-release revision number. + + switch( stage ) + { + case kVersionStageDevelopment: + s += sprintf( s, "d%u", revision ); + break; + + case kVersionStageAlpha: + s += sprintf( s, "a%u", revision ); + break; + + case kVersionStageBeta: + s += sprintf( s, "b%u", revision ); + break; + + case kVersionStageFinal: + + // A non-release revision of zero is a special case indicating the software is GM (at the golden master + // stage) and therefore, the non-release revision should not be added to the string. + + if( revision != 0 ) + { + s += sprintf( s, "f%u", revision ); + } + break; + + default: + dlog( kDebugLevelError, "invalid NumVersion stage (0x%02X)\n", stage ); + break; + } + return( inString ); +} + +//=========================================================================================================================== +// DebugTaskLevel +//=========================================================================================================================== + +DEBUG_EXPORT uint32_t DebugTaskLevel( void ) +{ + uint32_t level; + + level = 0; + +#if( TARGET_OS_VXWORKS ) + if( intContext() ) + { + level |= ( ( 1 << kDebugInterruptLevelShift ) & kDebugInterruptLevelMask ); + } +#endif + + return( level ); +} + +#if( TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE ) +//=========================================================================================================================== +// DebugWinEnableConsole +//=========================================================================================================================== + +#pragma warning( disable:4311 ) + +static void DebugWinEnableConsole( void ) +{ + static bool sConsoleEnabled = false; + BOOL result; + int fileHandle; + FILE * file; + int err; + + if( sConsoleEnabled ) + { + goto exit; + } + + // Create console window. + + result = AllocConsole(); + require_quiet( result, exit ); + + // Redirect stdin to the console stdin. + + fileHandle = _open_osfhandle( (long) GetStdHandle( STD_INPUT_HANDLE ), _O_TEXT ); + + #if( defined( __MWERKS__ ) ) + file = __handle_reopen( (unsigned long) fileHandle, "r", stdin ); + require_quiet( file, exit ); + #else + file = _fdopen( fileHandle, "r" ); + require_quiet( file, exit ); + + *stdin = *file; + #endif + + err = setvbuf( stdin, NULL, _IONBF, 0 ); + require_noerr_quiet( err, exit ); + + // Redirect stdout to the console stdout. + + fileHandle = _open_osfhandle( (long) GetStdHandle( STD_OUTPUT_HANDLE ), _O_TEXT ); + + #if( defined( __MWERKS__ ) ) + file = __handle_reopen( (unsigned long) fileHandle, "w", stdout ); + require_quiet( file, exit ); + #else + file = _fdopen( fileHandle, "w" ); + require_quiet( file, exit ); + + *stdout = *file; + #endif + + err = setvbuf( stdout, NULL, _IONBF, 0 ); + require_noerr_quiet( err, exit ); + + // Redirect stderr to the console stdout. + + fileHandle = _open_osfhandle( (long) GetStdHandle( STD_OUTPUT_HANDLE ), _O_TEXT ); + + #if( defined( __MWERKS__ ) ) + file = __handle_reopen( (unsigned long) fileHandle, "w", stderr ); + require_quiet( file, exit ); + #else + file = _fdopen( fileHandle, "w" ); + require_quiet( file, exit ); + + *stderr = *file; + #endif + + err = setvbuf( stderr, NULL, _IONBF, 0 ); + require_noerr_quiet( err, exit ); + + sConsoleEnabled = true; + +exit: + return; +} + +#pragma warning( default:4311 ) + +#endif // TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE + +#if( TARGET_OS_WIN32 ) +//=========================================================================================================================== +// DebugWinCharToTCharString +//=========================================================================================================================== + +static TCHAR * + DebugWinCharToTCharString( + const char * inCharString, + size_t inCharCount, + TCHAR * outTCharString, + size_t inTCharCountMax, + size_t * outTCharCount ) +{ + const char * src; + TCHAR * dst; + TCHAR * end; + + if( inCharCount == kSizeCString ) + { + inCharCount = strlen( inCharString ); + } + src = inCharString; + dst = outTCharString; + if( inTCharCountMax > 0 ) + { + inTCharCountMax -= 1; + if( inTCharCountMax > inCharCount ) + { + inTCharCountMax = inCharCount; + } + + end = dst + inTCharCountMax; + while( dst < end ) + { + *dst++ = (TCHAR) *src++; + } + *dst = 0; + } + if( outTCharCount ) + { + *outTCharCount = (size_t)( dst - outTCharString ); + } + return( outTCharString ); +} +#endif + +#if 0 +#pragma mark - +#pragma mark == Debugging == +#endif + +//=========================================================================================================================== +// DebugServicesTest +//=========================================================================================================================== + +DEBUG_EXPORT OSStatus DebugServicesTest( void ) +{ + OSStatus err; + char s[ 512 ]; + uint8_t * p; + uint8_t data[] = + { + 0x11, 0x22, 0x33, 0x44, + 0x55, 0x66, + 0x77, 0x88, 0x99, 0xAA, + 0xBB, 0xCC, 0xDD, + 0xEE, + 0xFF, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, + 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xA0, + 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71, 0x81, 0x91, 0xA1 + }; + + debug_initialize( kDebugOutputTypeMetaConsole ); + + // check's + + check( 0 && "SHOULD SEE: check" ); + check( 1 && "SHOULD *NOT* SEE: check (valid)" ); + check_string( 0, "SHOULD SEE: check_string" ); + check_string( 1, "SHOULD *NOT* SEE: check_string (valid)" ); + check_noerr( -123 ); + check_noerr( 10038 ); + check_noerr( 22 ); + check_noerr( 0 ); + check_noerr_string( -6712, "SHOULD SEE: check_noerr_string" ); + check_noerr_string( 0, "SHOULD *NOT* SEE: check_noerr_string (valid)" ); + check_translated_errno( 0 >= 0 && "SHOULD *NOT* SEE", -384, -999 ); + check_translated_errno( -1 >= 0 && "SHOULD SEE", -384, -999 ); + check_translated_errno( -1 >= 0 && "SHOULD SEE", 0, -999 ); + check_ptr_overlap( "SHOULD *NOT* SEE" ? 10 : 0, 10, 22, 10 ); + check_ptr_overlap( "SHOULD SEE" ? 10 : 0, 10, 5, 10 ); + check_ptr_overlap( "SHOULD SEE" ? 10 : 0, 10, 12, 6 ); + check_ptr_overlap( "SHOULD SEE" ? 12 : 0, 6, 10, 10 ); + check_ptr_overlap( "SHOULD SEE" ? 12 : 0, 10, 10, 10 ); + check_ptr_overlap( "SHOULD *NOT* SEE" ? 22 : 0, 10, 10, 10 ); + check_ptr_overlap( "SHOULD *NOT* SEE" ? 10 : 0, 10, 20, 10 ); + check_ptr_overlap( "SHOULD *NOT* SEE" ? 20 : 0, 10, 10, 10 ); + + // require's + + require( 0 && "SHOULD SEE", require1 ); + { err = kResponseErr; goto exit; } +require1: + require( 1 && "SHOULD *NOT* SEE", require2 ); + goto require2Good; +require2: + { err = kResponseErr; goto exit; } +require2Good: + require_string( 0 && "SHOULD SEE", require3, "SHOULD SEE: require_string" ); + { err = kResponseErr; goto exit; } +require3: + require_string( 1 && "SHOULD *NOT* SEE", require4, "SHOULD *NOT* SEE: require_string (valid)" ); + goto require4Good; +require4: + { err = kResponseErr; goto exit; } +require4Good: + require_quiet( 0 && "SHOULD SEE", require5 ); + { err = kResponseErr; goto exit; } +require5: + require_quiet( 1 && "SHOULD *NOT* SEE", require6 ); + goto require6Good; +require6: + { err = kResponseErr; goto exit; } +require6Good: + require_noerr( -1, require7 ); + { err = kResponseErr; goto exit; } +require7: + require_noerr( 0, require8 ); + goto require8Good; +require8: + { err = kResponseErr; goto exit; } +require8Good: + require_noerr_string( -2, require9, "SHOULD SEE: require_noerr_string"); + { err = kResponseErr; goto exit; } +require9: + require_noerr_string( 0, require10, "SHOULD *NOT* SEE: require_noerr_string (valid)" ); + goto require10Good; +require10: + { err = kResponseErr; goto exit; } +require10Good: + require_noerr_action_string( -3, require11, dlog( kDebugLevelMax, "action 1 (expected)\n" ), "require_noerr_action_string" ); + { err = kResponseErr; goto exit; } +require11: + require_noerr_action_string( 0, require12, dlog( kDebugLevelMax, "action 2\n" ), "require_noerr_action_string (valid)" ); + goto require12Good; +require12: + { err = kResponseErr; goto exit; } +require12Good: + require_noerr_quiet( -4, require13 ); + { err = kResponseErr; goto exit; } +require13: + require_noerr_quiet( 0, require14 ); + goto require14Good; +require14: + { err = kResponseErr; goto exit; } +require14Good: + require_noerr_action( -5, require15, dlog( kDebugLevelMax, "SHOULD SEE: action 3 (expected)\n" ) ); + { err = kResponseErr; goto exit; } +require15: + require_noerr_action( 0, require16, dlog( kDebugLevelMax, "SHOULD *NOT* SEE: action 4\n" ) ); + goto require16Good; +require16: + { err = kResponseErr; goto exit; } +require16Good: + require_noerr_action_quiet( -4, require17, dlog( kDebugLevelMax, "SHOULD SEE: action 5 (expected)\n" ) ); + { err = kResponseErr; goto exit; } +require17: + require_noerr_action_quiet( 0, require18, dlog( kDebugLevelMax, "SHOULD *NOT* SEE: action 6\n" ) ); + goto require18Good; +require18: + { err = kResponseErr; goto exit; } +require18Good: + require_action( 0 && "SHOULD SEE", require19, dlog( kDebugLevelMax, "SHOULD SEE: action 7 (expected)\n" ) ); + { err = kResponseErr; goto exit; } +require19: + require_action( 1 && "SHOULD *NOT* SEE", require20, dlog( kDebugLevelMax, "SHOULD *NOT* SEE: action 8\n" ) ); + goto require20Good; +require20: + { err = kResponseErr; goto exit; } +require20Good: + require_action_quiet( 0, require21, dlog( kDebugLevelMax, "SHOULD SEE: action 9 (expected)\n" ) ); + { err = kResponseErr; goto exit; } +require21: + require_action_quiet( 1, require22, dlog( kDebugLevelMax, "SHOULD *NOT* SEE: action 10\n" ) ); + goto require22Good; +require22: + { err = kResponseErr; goto exit; } +require22Good: + require_action_string( 0, require23, dlog( kDebugLevelMax, "SHOULD SEE: action 11 (expected)\n" ), "SHOULD SEE: require_action_string" ); + { err = kResponseErr; goto exit; } +require23: + require_action_string( 1, require24, dlog( kDebugLevelMax, "SHOULD *NOT* SEE: action 12\n" ), "SHOULD *NOT* SEE: require_action_string" ); + goto require24Good; +require24: + { err = kResponseErr; goto exit; } +require24Good: + +#if( defined( __MWERKS__ ) ) + #if( defined( __cplusplus ) && __option( exceptions ) ) + #define COMPILER_HAS_EXCEPTIONS 1 + #else + #define COMPILER_HAS_EXCEPTIONS 0 + #endif +#else + #if( defined( __cplusplus ) ) + #define COMPILER_HAS_EXCEPTIONS 1 + #else + #define COMPILER_HAS_EXCEPTIONS 0 + #endif +#endif + +#if( COMPILER_HAS_EXCEPTIONS ) + try + { + require_throw( 1 && "SHOULD *NOT* SEE" ); + require_throw( 0 && "SHOULD SEE" ); + } + catch( ... ) + { + goto require26Good; + } + { err = kResponseErr; goto exit; } +require26Good: +#endif + + // translate_errno + + err = translate_errno( 1 != -1, -123, -567 ); + require( ( err == 0 ) && "SHOULD *NOT* SEE", exit ); + + err = translate_errno( -1 != -1, -123, -567 ); + require( ( err == -123 ) && "SHOULD *NOT* SEE", exit ); + + err = translate_errno( -1 != -1, 0, -567 ); + require( ( err == -567 ) && "SHOULD *NOT* SEE", exit ); + + // debug_string + + debug_string( "debug_string" ); + + // DebugSNPrintF + + DebugSNPrintF( s, sizeof( s ), "%d", 1234 ); + require_action( strcmp( s, "1234" ) == 0, exit, err = -1 ); + + DebugSNPrintF( s, sizeof( s ), "%X", 0x2345 ); + require_action( strcmp( s, "2345" ) == 0, exit, err = -1 ); + + DebugSNPrintF( s, sizeof( s ), "%#s", "\05test" ); + require_action( strcmp( s, "test" ) == 0, exit, err = -1 ); + + DebugSNPrintF( s, sizeof( s ), "%##s", "\03www\05apple\03com" ); + require_action( strcmp( s, "www.apple.com." ) == 0, exit, err = -1 ); + + DebugSNPrintF( s, sizeof( s ), "%ld", (long) INT32_C( 2147483647 ) ); + require_action( strcmp( s, "2147483647" ) == 0, exit, err = -1 ); + + DebugSNPrintF( s, sizeof( s ), "%lu", (unsigned long) UINT32_C( 4294967295 ) ); + require_action( strcmp( s, "4294967295" ) == 0, exit, err = -1 ); + + #if( TYPE_LONGLONG_NATIVE ) + DebugSNPrintF( s, sizeof( s ), "%lld", (long_long_compat) INT64_C( 9223372036854775807 ) ); + require_action( strcmp( s, "9223372036854775807" ) == 0, exit, err = -1 ); + + DebugSNPrintF( s, sizeof( s ), "%lld", (long_long_compat) INT64_C( -9223372036854775807 ) ); + require_action( strcmp( s, "-9223372036854775807" ) == 0, exit, err = -1 ); + + DebugSNPrintF( s, sizeof( s ), "%llu", (unsigned_long_long_compat) UINT64_C( 18446744073709551615 ) ); + require_action( strcmp( s, "18446744073709551615" ) == 0, exit, err = -1 ); + #endif + + DebugSNPrintF( s, sizeof( s ), "%lb", (unsigned long) binary_32( 01111011, 01111011, 01111011, 01111011 ) ); + require_action( strcmp( s, "1111011011110110111101101111011" ) == 0, exit, err = -1 ); + + DebugSNPrintF( s, sizeof( s ), "%C", 0x41624364 ); // 'AbCd' + require_action( strcmp( s, "AbCd" ) == 0, exit, err = -1 ); + + #if( defined( MDNS_DEBUGMSGS ) ) + { + mDNSAddr maddr; + + memset( &maddr, 0, sizeof( maddr ) ); + maddr.type = mDNSAddrType_IPv4; + maddr.ip.v4.b[ 0 ] = 127; + maddr.ip.v4.b[ 1 ] = 0; + maddr.ip.v4.b[ 2 ] = 0; + maddr.ip.v4.b[ 3 ] = 1; + DebugSNPrintF( s, sizeof( s ), "%#a", &maddr ); + require_action( strcmp( s, "127.0.0.1" ) == 0, exit, err = -1 ); + + memset( &maddr, 0, sizeof( maddr ) ); + maddr.type = mDNSAddrType_IPv6; + maddr.ip.v6.b[ 0 ] = 0xFE; + maddr.ip.v6.b[ 1 ] = 0x80; + maddr.ip.v6.b[ 15 ] = 0x01; + DebugSNPrintF( s, sizeof( s ), "%#a", &maddr ); + require_action( strcmp( s, "FE80:0000:0000:0000:0000:0000:0000:0001" ) == 0, exit, err = -1 ); + } + #endif + + #if( AF_INET ) + { + struct sockaddr_in sa4; + + memset( &sa4, 0, sizeof( sa4 ) ); + sa4.sin_family = AF_INET; + p = (uint8_t *) &sa4.sin_port; + p[ 0 ] = (uint8_t)( ( 80 >> 8 ) & 0xFF ); + p[ 1 ] = (uint8_t)( 80 & 0xFF ); + p = (uint8_t *) &sa4.sin_addr.s_addr; + p[ 0 ] = (uint8_t)( ( INADDR_LOOPBACK >> 24 ) & 0xFF ); + p[ 1 ] = (uint8_t)( ( INADDR_LOOPBACK >> 16 ) & 0xFF ); + p[ 2 ] = (uint8_t)( ( INADDR_LOOPBACK >> 8 ) & 0xFF ); + p[ 3 ] = (uint8_t)( INADDR_LOOPBACK & 0xFF ); + DebugSNPrintF( s, sizeof( s ), "%##a", &sa4 ); + require_action( strcmp( s, "127.0.0.1:80" ) == 0, exit, err = -1 ); + } + #endif + + #if( AF_INET6 ) + { + struct sockaddr_in6 sa6; + + memset( &sa6, 0, sizeof( sa6 ) ); + sa6.sin6_family = AF_INET6; + p = (uint8_t *) &sa6.sin6_port; + p[ 0 ] = (uint8_t)( ( 80 >> 8 ) & 0xFF ); + p[ 1 ] = (uint8_t)( 80 & 0xFF ); + sa6.sin6_addr.s6_addr[ 0 ] = 0xFE; + sa6.sin6_addr.s6_addr[ 1 ] = 0x80; + sa6.sin6_addr.s6_addr[ 15 ] = 0x01; + sa6.sin6_scope_id = 2; + DebugSNPrintF( s, sizeof( s ), "%##a", &sa6 ); + require_action( strcmp( s, "[FE80:0000:0000:0000:0000:0000:0000:0001%2]:80" ) == 0, exit, err = -1 ); + } + #endif + + // Unicode + + DebugSNPrintF(s, sizeof(s), "%.*s", 4, "tes" ); + require_action( strcmp( s, "tes" ) == 0, exit, err = kResponseErr ); + + DebugSNPrintF(s, sizeof(s), "%.*s", 4, "test" ); + require_action( strcmp( s, "test" ) == 0, exit, err = kResponseErr ); + + DebugSNPrintF(s, sizeof(s), "%.*s", 4, "testing" ); + require_action( strcmp( s, "test" ) == 0, exit, err = kResponseErr ); + + DebugSNPrintF(s, sizeof(s), "%.*s", 4, "te\xC3\xA9" ); + require_action( strcmp( s, "te\xC3\xA9" ) == 0, exit, err = kResponseErr ); + + DebugSNPrintF(s, sizeof(s), "%.*s", 4, "te\xC3\xA9ing" ); + require_action( strcmp( s, "te\xC3\xA9" ) == 0, exit, err = kResponseErr ); + + DebugSNPrintF(s, sizeof(s), "%.*s", 4, "tes\xC3\xA9ing" ); + require_action( strcmp( s, "tes" ) == 0, exit, err = kResponseErr ); + + DebugSNPrintF(s, sizeof(s), "%.*s", 4, "t\xed\x9f\xbf" ); + require_action( strcmp( s, "t\xed\x9f\xbf" ) == 0, exit, err = kResponseErr ); + + DebugSNPrintF(s, sizeof(s), "%.*s", 4, "t\xed\x9f\xbfing" ); + require_action( strcmp( s, "t\xed\x9f\xbf" ) == 0, exit, err = kResponseErr ); + + DebugSNPrintF(s, sizeof(s), "%.*s", 4, "te\xed\x9f\xbf" ); + require_action( strcmp( s, "te" ) == 0, exit, err = kResponseErr ); + + DebugSNPrintF(s, sizeof(s), "%.*s", 4, "te\xed\x9f\xbfing" ); + require_action( strcmp( s, "te" ) == 0, exit, err = kResponseErr ); + + DebugSNPrintF(s, sizeof(s), "%.*s", 7, "te\xC3\xA9\xed\x9f\xbfing" ); + require_action( strcmp( s, "te\xC3\xA9\xed\x9f\xbf" ) == 0, exit, err = kResponseErr ); + + DebugSNPrintF(s, sizeof(s), "%.*s", 6, "te\xC3\xA9\xed\x9f\xbfing" ); + require_action( strcmp( s, "te\xC3\xA9" ) == 0, exit, err = kResponseErr ); + + DebugSNPrintF(s, sizeof(s), "%.*s", 5, "te\xC3\xA9\xed\x9f\xbfing" ); + require_action( strcmp( s, "te\xC3\xA9" ) == 0, exit, err = kResponseErr ); + + #if( TARGET_RT_BIG_ENDIAN ) + DebugSNPrintF( s, sizeof( s ), "%S", "\x00" "a" "\x00" "b" "\x00" "c" "\x00" "d" "\x00" "\x00" ); + require_action( strcmp( s, "abcd" ) == 0, exit, err = -1 ); + #else + DebugSNPrintF( s, sizeof( s ), "%S", "a" "\x00" "b" "\x00" "c" "\x00" "d" "\x00" "\x00" "\x00" ); + require_action( strcmp( s, "abcd" ) == 0, exit, err = -1 ); + #endif + + DebugSNPrintF( s, sizeof( s ), "%S", + "\xFE\xFF" "\x00" "a" "\x00" "b" "\x00" "c" "\x00" "d" "\x00" "\x00" ); // Big Endian BOM + require_action( strcmp( s, "abcd" ) == 0, exit, err = -1 ); + + DebugSNPrintF( s, sizeof( s ), "%S", + "\xFF\xFE" "a" "\x00" "b" "\x00" "c" "\x00" "d" "\x00" "\x00" "\x00" ); // Little Endian BOM + require_action( strcmp( s, "abcd" ) == 0, exit, err = -1 ); + + DebugSNPrintF( s, sizeof( s ), "%#S", "\x00" "a" "\x00" "b" "\x00" "c" "\x00" "d" "\x00" "\x00" ); // Big Endian + require_action( strcmp( s, "abcd" ) == 0, exit, err = -1 ); + + DebugSNPrintF( s, sizeof( s ), "%##S", "a" "\x00" "b" "\x00" "c" "\x00" "d" "\x00" "\x00" "\x00" ); // Little Endian + require_action( strcmp( s, "abcd" ) == 0, exit, err = -1 ); + + DebugSNPrintF( s, sizeof( s ), "%.*S", + 4, "\xFE\xFF" "\x00" "a" "\x00" "b" "\x00" "c" "\x00" "d" ); // Big Endian BOM + require_action( strcmp( s, "abc" ) == 0, exit, err = -1 ); + + DebugSNPrintF( s, sizeof( s ), "%.*S", + 4, "\xFF\xFE" "a" "\x00" "b" "\x00" "c" "\x00" "d" "\x00" ); // Little Endian BOM + require_action( strcmp( s, "abc" ) == 0, exit, err = -1 ); + + #if( TARGET_RT_BIG_ENDIAN ) + DebugSNPrintF( s, sizeof( s ), "%.*S", 3, "\x00" "a" "\x00" "b" "\x00" "c" "\x00" "d" ); + require_action( strcmp( s, "abc" ) == 0, exit, err = -1 ); + #else + DebugSNPrintF( s, sizeof( s ), "%.*S", 3, "a" "\x00" "b" "\x00" "c" "\x00" "d" "\x00" ); + require_action( strcmp( s, "abc" ) == 0, exit, err = -1 ); + #endif + + DebugSNPrintF( s, sizeof( s ), "%#.*S", 3, "\x00" "a" "\x00" "b" "\x00" "c" "\x00" "d" ); // Big Endian + require_action( strcmp( s, "abc" ) == 0, exit, err = -1 ); + + DebugSNPrintF( s, sizeof( s ), "%##.*S", 3, "a" "\x00" "b" "\x00" "c" "\x00" "d" "\x00" ); // Little Endian + require_action( strcmp( s, "abc" ) == 0, exit, err = -1 ); + + // Misc + + DebugSNPrintF( s, sizeof( s ), "%U", "\x10\xb8\xa7\x6b" "\xad\x9d" "\xd1\x11" "\x80\xb4" "\x00\xc0\x4f\xd4\x30\xc8" ); + require_action( strcmp( s, "6ba7b810-9dad-11d1-80b4-00c04fd430c8" ) == 0, exit, err = -1 ); + + DebugSNPrintF( s, sizeof( s ), "%m", 0 ); + require_action( strcmp( s, "no error" ) == 0, exit, err = -1 ); + + DebugSNPrintF( s, sizeof( s ), "%lm", (long) 0 ); + require_action( strcmp( s, "no error" ) == 0, exit, err = -1 ); + + DebugSNPrintF( s, sizeof( s ), "\"%H\"", "\x6b\xa7\xb8\x10\x9d\xad\x11\xd1\x80\xb4\x00\xc0\x4f\xd4\x30\xc8", 16, 16 ); + DebugPrintF( kDebugLevelMax, "%s\n\n", s ); + + DebugSNPrintF( s, sizeof( s ), "\"%H\"", + "\x6b\xa7\xb8\x10\x9d\xad\x11\xd1\x80\xb4\x00\xc0\x4f\xd4\x30\xc8" + "\x6b\xa7\xb8\x10\x9d\xad\x11\xd1\x80\xb4\x00\xc0\x4f\xd4\x30\xc8", + 32, 32 ); + DebugPrintF( kDebugLevelMax, "%s\n\n", s ); + + DebugSNPrintF( s, sizeof( s ), "\"%H\"", "\x6b\xa7", 2, 2 ); + DebugPrintF( kDebugLevelMax, "%s\n\n", s ); + + // Hex Dumps + + s[ 0 ] = '\0'; + DebugHexDump( kDebugLevelMax, 0, "My Label", kSizeCString, 0, NULL, 0, data, data, sizeof( data ), + kDebugFlagsNone, s, sizeof( s ) ); + DebugPrintF( kDebugLevelMax, "%s\n", s ); + + s[ 0 ] = '\0'; + DebugHexDump( kDebugLevelMax, 0, NULL, 0, 0, NULL, 0, data, data, sizeof( data ), + kDebugFlagsNoAddress | kDebugFlagsNoOffset, s, sizeof( s ) ); + DebugPrintF( kDebugLevelMax, "%s\n", s ); + + s[ 0 ] = '\0'; + DebugHexDump( kDebugLevelMax, 0, "My Label", kSizeCString, 0, NULL, 0, data, data, sizeof( data ), + kDebugFlagsNoAddress | kDebugFlagsNoOffset, s, sizeof( s ) ); + DebugPrintF( kDebugLevelMax, "%s\n", s ); + + s[ 0 ] = '\0'; + DebugHexDump( kDebugLevelMax, 0, "My Label", kSizeCString, 0, NULL, 0, data, data, sizeof( data ), + kDebugFlagsNoAddress, s, sizeof( s ) ); + DebugPrintF( kDebugLevelMax, "%s\n", s ); + + s[ 0 ] = '\0'; + DebugHexDump( kDebugLevelMax, 0, NULL, 0, 0, NULL, 0, data, data, sizeof( data ), + kDebugFlagsNoOffset, s, sizeof( s ) ); + DebugPrintF( kDebugLevelMax, "%s\n", s ); + + s[ 0 ] = '\0'; + DebugHexDump( kDebugLevelMax, 0, NULL, 0, 0, NULL, 0, data, data, sizeof( data ), + kDebugFlagsNoAddress, s, sizeof( s ) ); + DebugPrintF( kDebugLevelMax, "%s\n", s ); + + s[ 0 ] = '\0'; + DebugHexDump( kDebugLevelMax, 0, NULL, 0, 0, NULL, 0, data, data, sizeof( data ), + kDebugFlagsNoOffset, s, sizeof( s ) ); + DebugPrintF( kDebugLevelMax, "%s\n", s ); + + s[ 0 ] = '\0'; + DebugHexDump( kDebugLevelMax, 0, NULL, 0, 0, NULL, 0, data, data, sizeof( data ), + kDebugFlagsNoByteCount, s, sizeof( s ) ); + DebugPrintF( kDebugLevelMax, "%s\n", s ); + + s[ 0 ] = '\0'; + DebugHexDump( kDebugLevelMax, 0, NULL, 0, 0, NULL, 0, "\x41\x62\x43\x64", "\x41\x62\x43\x64", 4, // 'AbCd' + kDebugFlagsNoAddress | kDebugFlagsNoOffset | kDebugFlagsNoNewLine | + kDebugFlagsNo32BitSeparator | kDebugFlagsNo16ByteHexPad | kDebugFlagsNoByteCount, + s, sizeof( s ) ); + DebugPrintF( kDebugLevelMax, "%s\n", s ); + + s[ 0 ] = '\0'; + DebugHexDump( kDebugLevelMax, 0, NULL, 0, 0, NULL, 0, data, data, sizeof( data ), + kDebugFlagsNoAddress | kDebugFlagsNoOffset | kDebugFlagsNoASCII | kDebugFlagsNoNewLine | + kDebugFlags16BitSeparator | kDebugFlagsNo32BitSeparator | + kDebugFlagsNo16ByteHexPad | kDebugFlagsNoByteCount, s, sizeof( s ) ); + DebugPrintF( kDebugLevelMax, "%s\n", s ); + + s[ 0 ] = '\0'; + DebugHexDump( kDebugLevelMax, 8, NULL, 0, 0, NULL, 0, data, data, sizeof( data ), kDebugFlagsNone, s, sizeof( s ) ); + DebugPrintF( kDebugLevelMax, "%s\n", s ); + + // dlog's + + dlog( kDebugLevelNotice, "dlog\n" ); + dlog( kDebugLevelNotice, "dlog integer: %d\n", 123 ); + dlog( kDebugLevelNotice, "dlog string: \"%s\"\n", "test string" ); + dlogmem( kDebugLevelNotice, data, sizeof( data ) ); + + // Done + + DebugPrintF( kDebugLevelMax, "\n\nALL TESTS DONE\n\n" ); + err = kNoErr; + +exit: + if( err ) + { + DebugPrintF( kDebugLevelMax, "\n\n### TEST FAILED ###\n\n" ); + } + return( err ); +} + +#endif // DEBUG diff --git a/mDNSShared/DebugServices.h b/mDNSShared/DebugServices.h new file mode 100644 index 0000000..7111fa2 --- /dev/null +++ b/mDNSShared/DebugServices.h @@ -0,0 +1,1628 @@ +/* -*- Mode: C; tab-width: 4 -*- + * + * Copyright (c) 1997-2004 Apple Computer, Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + + Change History (most recent first): + +$Log: DebugServices.h,v $ +Revision 1.5 2006/08/14 23:24:56 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + +Revision 1.4 2004/04/15 08:59:08 bradley +Removed deprecated debug and log levels and replaced them with modern equivalents. + +Revision 1.3 2004/04/08 09:29:55 bradley +Manually do host->network byte order conversion to avoid needing libraries for htons/htonl. Changed +hex dumps to better separate hex and ASCII. Added support for %.8a syntax in DebugSNPrintF for Fibre +Channel addresses (00:11:22:33:44:55:66:77). Fixed a few places where HeaderDoc was incorrect. + +Revision 1.2 2004/03/07 05:59:34 bradley +Sync'd with internal version: Added expect macros, error codes, and CoreServices exclusion. + +Revision 1.1 2004/01/30 02:27:30 bradley +Debugging support for various platforms. + +*/ + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @header DebugServices + + Debugging Library +*/ + +#ifndef __DEBUG_SERVICES__ +#define __DEBUG_SERVICES__ + +#include + +#include "CommonServices.h" + +#if( TARGET_OS_VXWORKS ) + #include "logLib.h" +#endif + +#if 0 +#pragma mark == Settings == +#endif + +//=========================================================================================================================== +// Settings +//=========================================================================================================================== + +// General + +#if( !defined( DEBUG ) ) + #define DEBUG 0 +#endif + +#if( defined( NDEBUG ) && DEBUG ) + #error NDEBUG defined and DEBUG is also enabled...they need to be in-sync +#endif + +// AssertMacros.h/Debugging.h overrides. + +#if( !defined( DEBUG_OVERRIDE_APPLE_MACROS ) ) + #define DEBUG_OVERRIDE_APPLE_MACROS 1 +#endif + +// Routine name. Uses ISO __func__ where possible. Otherwise, uses the best thing that is available (if anything). + +#if( defined( __MWERKS__ ) || ( __GNUC__ > 2 ) || ( ( __GNUC__ == 2 ) && ( __GNUC_MINOR__ >= 9 ) ) ) + #define __ROUTINE__ __func__ +#elif( defined( __GNUC__ ) ) + #define __ROUTINE__ __PRETTY_FUNCTION__ +#elif( defined( _MSC_VER ) && !defined( _WIN32_WCE ) ) + #define __ROUTINE__ __FUNCTION__ +#else + #define __ROUTINE__ "" +#endif + +// Variable argument macro support. Use ANSI C99 __VA_ARGS__ where possible. Otherwise, use the next best thing. + +#if( defined( __GNUC__ ) ) + #if( ( __GNUC__ > 3 ) || ( ( __GNUC__ == 3 ) && ( __GNUC_MINOR__ >= 3) ) ) + #define DEBUG_C99_VA_ARGS 1 + #define DEBUG_GNU_VA_ARGS 0 + #else + #define DEBUG_C99_VA_ARGS 0 + #define DEBUG_GNU_VA_ARGS 1 + #endif +#elif( defined( __MWERKS__ ) ) + #define DEBUG_C99_VA_ARGS 1 + #define DEBUG_GNU_VA_ARGS 0 +#else + #define DEBUG_C99_VA_ARGS 0 + #define DEBUG_GNU_VA_ARGS 0 +#endif + +#if 0 +#pragma mark == Output == +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined DEBUG_FPRINTF_ENABLED + + @abstract Enables ANSI C fprintf output. +*/ + +#if( !defined( DEBUG_FPRINTF_ENABLED ) ) + #if( !TARGET_API_MAC_OSX_KERNEL && !TARGET_OS_WINDOWS_CE ) + #define DEBUG_FPRINTF_ENABLED 1 + #else + #define DEBUG_FPRINTF_ENABLED 0 + #endif +#else + #if( TARGET_API_MAC_OSX_KERNEL || TARGET_OS_WINDOWS_CE ) + #error fprintf enabled, but not supported on Mac OS X kernel or Windows CE + #endif +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined DEBUG_MAC_OS_X_IOLOG_ENABLED + + @abstract Enables IOLog (Mac OS X Kernel) output. +*/ + +#if( !defined( DEBUG_MAC_OS_X_IOLOG_ENABLED ) ) + #define DEBUG_MAC_OS_X_IOLOG_ENABLED TARGET_API_MAC_OSX_KERNEL +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined DEBUG_KPRINTF_ENABLED + + @abstract Enables kprintf (Mac OS X Kernel) output. +*/ + +#if( !defined( DEBUG_KPRINTF_ENABLED ) ) + #define DEBUG_KPRINTF_ENABLED TARGET_API_MAC_OSX_KERNEL +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined DEBUG_IDEBUG_ENABLED + + @abstract Enables iDebug (Mac OS X user and Kernel) output. + + @discussion + + For Mac OS X kernel development, iDebug is enabled by default because we can dynamically check for the presence + of iDebug via some exported IOKit symbols. Mac OS X app usage doesn't allow dynamic detection because it relies + on statically linking to the iDebugServices.cp file so for Mac OS X app usage, you have to manually enable iDebug. +*/ + +#if( !defined( DEBUG_IDEBUG_ENABLED ) ) + #define DEBUG_IDEBUG_ENABLED TARGET_API_MAC_OSX_KERNEL +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined DEBUG_CORE_SERVICE_ASSERTS_ENABLED + + @abstract Controls whether Core Services assert handling is enabled. Enabling requires CoreServices framework. +*/ + +#if( !defined( DEBUG_CORE_SERVICE_ASSERTS_ENABLED ) ) + #if( defined( __DEBUGGING__ ) ) + #define DEBUG_CORE_SERVICE_ASSERTS_ENABLED 1 + #else + #define DEBUG_CORE_SERVICE_ASSERTS_ENABLED 0 + #endif +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @typedef DebugOutputType + + @abstract Type of debug output (i.e. where the output goes). +*/ + +typedef uint32_t DebugOutputType; + +#define kDebugOutputTypeNone 0x6E6F6E65U // 'none' - no params +#define kDebugOutputTypeCustom 0x63757374U // 'cust' - 1st param = function ptr, 2nd param = context +#define kDebugOutputTypeFPrintF 0x66707269U // 'fpri' - 1st param = DebugOutputTypeFlags [, 2nd param = filename] +#define kDebugOutputTypeiDebug 0x69646267U // 'idbg' - no params +#define kDebugOutputTypeKPrintF 0x6B707266U // 'kprf' - no params +#define kDebugOutputTypeMacOSXIOLog 0x696C6F67U // 'ilog' - no params +#define kDebugOutputTypeMacOSXLog 0x786C6F67U // 'xlog' - no params +#define kDebugOutputTypeWindowsDebugger 0x77696E64U // 'wind' - no params +#define kDebugOutputTypeWindowsEventLog 0x7765766CU // 'wevl' - 1st param = C-string name, 2nd param = HMODULE or NULL. + +// Console meta output kind - Any kind of Console output (in horizontal order of preference): +// +// Mac OS X = ANSI printf (viewable in Console.app) +// Mac OS X Kernel = IOLog (/var/log/system.log) or kprintf (serial). +// Windows = ANSI printf (Console window) or OutputDebugString (debugger). +// Other = ANSI printf (viewer varies). + +#define kDebugOutputTypeMetaConsole 0x434F4E53U // 'CONS' - no params + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @typedef DebugOutputTypeFlags + + @abstract Flags controlling how the output type is configured. + + @constant kDebugOutputTypeFlagsTypeMask Bit mask for the output type (e.g. stdout, stderr, file, etc.). + @constant kDebugOutputTypeFlagsStdOut fprintf should go to stdout. + @constant kDebugOutputTypeFlagsStdErr fprintf should go to stderr. + @constant kDebugOutputTypeFlagsFile fprintf should go to a specific file (filename passed as va_arg). +*/ + +typedef unsigned int DebugOutputTypeFlags; + +#define kDebugOutputTypeFlagsTypeMask 0xF +#define kDebugOutputTypeFlagsStdOut 1 +#define kDebugOutputTypeFlagsStdErr 2 +#define kDebugOutputTypeFlagsFile 10 + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @typedef DebugOutputFunctionPtr + + @abstract Function ptr for a custom callback to print debug output. +*/ + +typedef void ( *DebugOutputFunctionPtr )( char *inData, size_t inSize, void *inContext ); + +//=========================================================================================================================== +// Constants +//=========================================================================================================================== + +#if 0 +#pragma mark == Flags == +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @typedef DebugFlags + + @abstract Flags controlling how output is printed. +*/ + +typedef uint32_t DebugFlags; + +#define kDebugFlagsNone 0 +#define kDebugFlagsNoAddress ( 1 << 0 ) +#define kDebugFlagsNoOffset ( 1 << 1 ) +#define kDebugFlags32BitOffset ( 1 << 2 ) +#define kDebugFlagsNoASCII ( 1 << 3 ) +#define kDebugFlagsNoNewLine ( 1 << 4 ) +#define kDebugFlags8BitSeparator ( 1 << 5 ) +#define kDebugFlags16BitSeparator ( 1 << 6 ) +#define kDebugFlagsNo32BitSeparator ( 1 << 7 ) +#define kDebugFlagsNo16ByteHexPad ( 1 << 8 ) +#define kDebugFlagsNoByteCount ( 1 << 9 ) + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @enum DebugTaskLevelFlags + + @abstract Flags indicating the task level. +*/ + +enum +{ + kDebugInterruptLevelShift = 0, + kDebugInterruptLevelMask = 0x00000007, + kDebugInVBLTaskMask = 0x00000010, + kDebugInDeferredTaskMask = 0x00000020, + kDebugInSecondaryInterruptHandlerMask = 0x00000040, + kDebugPageFaultFatalMask = 0x00000100, // There should be a "kPageFaultFatalMask" in Debugging.h. + kDebugMPTaskLevelMask = 0x00000200, // There should be a "kMPTaskLevelMask" in Debugging.h. + kDebugInterruptDepthShift = 16, + kDebugInterruptDepthMask = 0x00FF0000 +}; + +#define DebugExtractTaskLevelInterruptLevel( LEVEL ) \ + ( ( ( LEVEL ) & kDebugInterruptLevelMask ) >> kDebugInterruptLevelShift ) + +#define DebugExtractTaskLevelInterruptDepth( LEVEL ) \ + ( ( ( LEVEL ) & kDebugInterruptDepthMask ) >> kDebugInterruptDepthShift ) + +#if 0 +#pragma mark == Levels == +#endif + +//=========================================================================================================================== +// Constants & Types - Levels +//=========================================================================================================================== + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @typedef DebugLevel + + @abstract Level used to control debug logging. +*/ + +typedef int32_t DebugLevel; + +// Levels + +#define kDebugLevelMask 0x0000FFFF +#define kDebugLevelChatty 100 +#define kDebugLevelVerbose 500 +#define kDebugLevelTrace 800 +#define kDebugLevelInfo 1000 +#define kDebugLevelNotice 3000 +#define kDebugLevelWarning 5000 +#define kDebugLevelAssert 6000 +#define kDebugLevelRequire 7000 +#define kDebugLevelError 8000 +#define kDebugLevelCritical 9000 +#define kDebugLevelAlert 10000 +#define kDebugLevelEmergency 11000 +#define kDebugLevelTragic 12000 +#define kDebugLevelMax 0x0000FFFF + +// Level Flags + +#define kDebugLevelFlagMask 0xFFFF0000 +#define kDebugLevelFlagStackTrace 0x00010000 +#define kDebugLevelFlagDebugBreak 0x00020000 + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @typedef LogLevel + + @abstract Level used to control which events are logged. +*/ + +typedef int32_t LogLevel; + +#define kLogLevelUninitialized -1L +#define kLogLevelAll 0L +#define kLogLevelChatty 100L +#define kLogLevelVerbose 500L +#define kLogLevelTrace 800L +#define kLogLevelInfo 1000L +#define kLogLevelNotice 3000L +#define kLogLevelWarning 4000L +#define kLogLevelAssert 6000L +#define kLogLevelRequire 7000L +#define kLogLevelError 8000L +#define kLogLevelCritical 9000L +#define kLogLevelAlert 10000L +#define kLogLevelEmergency 11000L +#define kLogLevelTragic 12000L +#define kLogLevelOff 0x0000FFFEL + +#if 0 +#pragma mark == Properties == +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @typedef DebugPropertyTag + + @abstract Tag for properties. +*/ + +typedef uint32_t DebugPropertyTag; + +#define kDebugPropertyTagPrintLevelMin 0x6D696E70U // 'minp' Get: 1st param = DebugLevel * + // Set: 1st param = DebugLevel + +#define kDebugPropertyTagPrintLevel kDebugPropertyTagPrintLevelMin + +#define kDebugPropertyTagPrintLevelMax 0x706D786CU // 'maxp' Get: 1st param = DebugLevel * + // Set: 1st param = DebugLevel + +#define kDebugPropertyTagBreakLevel 0x62726B6CU // 'brkl' Get: 1st param = DebugLevel * + // Set: 1st param = DebugLevel +#if 0 +#pragma mark == General macros == +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined DEBUG_UNUSED + + @abstract Macro to mark a paramter as unused to avoid unused parameter warnings. + + @discussion + + There is no universally supported pragma/attribute for indicating a variable is unused. DEBUG_UNUSED lets us + indicate a variable is unused in a manner that is supported by most compilers. +*/ + +#define DEBUG_UNUSED( X ) (void)( X ) + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined DEBUG_USE_ONLY + + @abstract Macro to mark a variable as used only when debugging is enabled. + + @discussion + + Variables are sometimes needed only for debugging. When debugging is turned off, these debug-only variables generate + compiler warnings about unused variables. To eliminate these warnings, use these macros to indicate variables that + are only used for debugging. +*/ + +#if( DEBUG ) + #define DEBUG_USE_ONLY( X ) +#else + #define DEBUG_USE_ONLY( X ) (void)( X ) +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined DEBUG_LOCAL + + @abstract Macros to make variables and functions static when debugging is off, but extern when debugging is on. + + @discussion + + Rather than using "static" directly, using this macros allows you to access these variables external while + debugging without being penalized for production builds. +*/ + +#if( DEBUG ) + #define DEBUG_LOCAL +#else + #define DEBUG_LOCAL static +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined DEBUG_STATIC + + @abstract Macros to make variables and functions static when debugging is off, but extern when debugging is on. + + @discussion + + Rather than using "static" directly, using this macros allows you to access these variables external while + debugging without being penalized for production builds. +*/ + +#if( DEBUG ) + #define DEBUG_STATIC +#else + #define DEBUG_STATIC static +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined DEBUG_EXPORT + + @abstract Macros to export variables. + + @discussion + + "__private_extern__" is a hack for IOKit to allow symbols to be exported from compilation units, but + // not exported outside a driver (IOKit uses a lame global namespace for symbols). This still does not + // solve the problem of multiple drivers in the same dependency chain since they share symbols. +*/ + +#if( TARGET_API_MAC_OSX_KERNEL ) + #define DEBUG_EXPORT __private_extern__ +#else + #define DEBUG_EXPORT extern +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined debug_add + + @abstract Macro to add (or subtract if negative) a value when debugging is on. Does nothing if debugging is off. +*/ + +#if( DEBUG ) + #define debug_add( A, B ) ( A ) += ( B ) +#else + #define debug_add( A, B ) +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined debug_perform + + @abstract Macro to perform something in debug-only builds. +*/ + +#if( DEBUG ) + #define debug_perform( X ) do { X; } while( 0 ) +#else + #define debug_perform( X ) +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @function translate_errno + + @abstract Returns 0 if the test success. If the test fails, returns errno if non-zero and othewise the alternate error. +*/ + +#define translate_errno( TEST, ERRNO, ALTERNATE_ERROR ) ( ( TEST ) ? 0 : ( ERRNO ) ? ( ERRNO ) : ( ALTERNATE_ERROR ) ) + +#if 0 +#pragma mark == Compile Time macros == +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined check_compile_time + + @abstract Performs a compile-time check of something such as the size of an int. + + @discussion + + This declares an array with a size that is determined by a compile-time expression. If the expression evaluates + to 0, the array has a size of -1, which is illegal and generates a compile-time error. + + For example: + + check_compile_time( sizeof( int ) == 4 ); + + Note: This only works with compile-time expressions. + Note: This only works in places where extern declarations are allowed (e.g. global scope). + + References: + + + + + Note: The following macros differ from the macros on the www.jaggersoft.com web site because those versions do not + work with GCC due to GCC allow a zero-length array. Using a -1 condition turned out to be more portable. +*/ + +#define check_compile_time( X ) extern int debug_compile_time_name[ ( X ) ? 1 : -1 ] + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined check_compile_time_code + + @abstract Perform a compile-time check, suitable for placement in code, of something such as the size of an int. + + @discussion + + This creates a switch statement with an existing case for 0 and an additional case using the result of a + compile-time expression. A switch statement cannot have two case labels with the same constant so if the + compile-time expression evaluates to 0, it is illegal and generates a compile-time error. If the compile-time + expression does not evaluate to 0, the resulting value is used as the case label and it compiles without error. + + For example: + + check_compile_time_code( sizeof( int ) == 4 ); + + Note: This only works with compile-time expressions. + Note: This does not work in a global scope so it must be inside a function. + + References: + + + +*/ + +#define check_compile_time_code( X ) switch( 0 ) { case 0: case X:; } + +#if 0 +#pragma mark == check macros == +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined check + + @abstract Check that an expression is true (non-zero). + + @discussion + + If expression evalulates to false, this prints debugging information (actual expression string, file, line number, + function name, etc.) using the default debugging output method. + + Code inside check() statements is not compiled into production builds. +*/ + +#if( DEBUG_OVERRIDE_APPLE_MACROS ) + #undef check +#endif +#if( !defined( check ) ) + #if( DEBUG ) + #define check( X ) \ + do \ + { \ + if( !( X ) ) \ + { \ + debug_print_assert( 0, #X, NULL, __FILE__, __LINE__, __ROUTINE__ ); \ + } \ + } while( 0 ) + #else + #define check( X ) + #endif +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined check_string + + @abstract Check that an expression is true (non-zero) with an explanation. + + @discussion + + If expression evalulates to false, this prints debugging information (actual expression string, file, line number, + function name, etc.) and a custom explanation string using the default debugging output method. + + Code inside check_string() statements is not compiled into production builds. +*/ + +#if( DEBUG_OVERRIDE_APPLE_MACROS ) + #undef check_string +#endif +#if( !defined( check_string ) ) + #if( DEBUG ) + #define check_string( X, STR ) \ + do \ + { \ + if( !( X ) ) \ + { \ + debug_print_assert( 0, #X, STR, __FILE__, __LINE__, __ROUTINE__ ); \ + } \ + \ + } while( 0 ) + #else + #define check_string( X, STR ) + #endif +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined check_noerr + + @abstract Check that an error code is noErr (0). + + @discussion + + If the error code is non-0, this prints debugging information (actual expression string, file, line number, + function name, etc.) using the default debugging output method. + + Code inside check_noerr() statements is not compiled into production builds. +*/ + +#if( DEBUG_OVERRIDE_APPLE_MACROS ) + #undef check_noerr +#endif +#if( !defined( check_noerr ) ) + #if( DEBUG ) + #define check_noerr( ERR ) \ + do \ + { \ + int_least32_t localErr; \ + \ + localErr = (int_least32_t)( ERR ); \ + if( localErr != 0 ) \ + { \ + debug_print_assert( localErr, NULL, NULL, __FILE__, __LINE__, __ROUTINE__ ); \ + } \ + \ + } while( 0 ) + #else + #define check_noerr( ERR ) + #endif +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined check_noerr_string + + @abstract Check that an error code is noErr (0) with an explanation. + + @discussion + + If the error code is non-0, this prints debugging information (actual expression string, file, line number, + function name, etc.) and a custom explanation string using the default debugging output method. + + Code inside check_noerr_string() statements is not compiled into production builds. +*/ + +#if( DEBUG_OVERRIDE_APPLE_MACROS ) + #undef check_noerr_string +#endif +#if( !defined( check_noerr_string ) ) + #if( DEBUG ) + #define check_noerr_string( ERR, STR ) \ + do \ + { \ + int_least32_t localErr; \ + \ + localErr = (int_least32_t)( ERR ); \ + if( localErr != 0 ) \ + { \ + debug_print_assert( localErr, NULL, STR, __FILE__, __LINE__, __ROUTINE__ ); \ + } \ + \ + } while( 0 ) + #else + #define check_noerr_string( ERR, STR ) + #endif +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined check_translated_errno + + @abstract Check a condition and prints errno (if non-zero) to the log. + + @discussion + + Code inside check_translated_errno() statements is not compiled into production builds. +*/ + +#if( !defined( check_translated_errno ) ) + #if( DEBUG ) + #define check_translated_errno( TEST, ERRNO, ALTERNATE_ERROR ) \ + do \ + { \ + if( !( TEST ) ) \ + { \ + int_least32_t localErr; \ + \ + localErr = (int_least32_t)( ERRNO ); \ + localErr = ( localErr != 0 ) ? localErr : (int_least32_t)( ALTERNATE_ERROR ); \ + debug_print_assert( localErr, #TEST, NULL, __FILE__, __LINE__, __ROUTINE__ ); \ + } \ + \ + } while( 0 ) + #else + #define check_translated_errno( TEST, ERRNO, ALTERNATE_ERROR ) + #endif +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined check_ptr_overlap + + @abstract Checks that two ptrs do not overlap. +*/ + +#define check_ptr_overlap( P1, P1_SIZE, P2, P2_SIZE ) \ + do \ + { \ + check( !( ( (uintptr_t)( P1 ) >= (uintptr_t)( P2 ) ) && \ + ( (uintptr_t)( P1 ) < ( ( (uintptr_t)( P2 ) ) + ( P2_SIZE ) ) ) ) ); \ + check( !( ( (uintptr_t)( P2 ) >= (uintptr_t)( P1 ) ) && \ + ( (uintptr_t)( P2 ) < ( ( (uintptr_t)( P1 ) ) + ( P1_SIZE ) ) ) ) ); \ + \ + } while( 0 ) + +#if 0 +#pragma mark == require macros == +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined require + + @abstract Requires that an expression evaluate to true. + + @discussion + + If expression evalulates to false, this prints debugging information (actual expression string, file, line number, + function name, etc.) using the default debugging output method then jumps to a label. +*/ + +#if( DEBUG_OVERRIDE_APPLE_MACROS ) + #undef require +#endif +#if( !defined( require ) ) + #define require( X, LABEL ) \ + do \ + { \ + if( !( X ) ) \ + { \ + debug_print_assert( 0, #X, NULL, __FILE__, __LINE__, __ROUTINE__ ); \ + goto LABEL; \ + } \ + \ + } while( 0 ) +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined require_string + + @abstract Requires that an expression evaluate to true with an explanation. + + @discussion + + If expression evalulates to false, this prints debugging information (actual expression string, file, line number, + function name, etc.) and a custom explanation string using the default debugging output method then jumps to a label. +*/ + +#if( DEBUG_OVERRIDE_APPLE_MACROS ) + #undef require_string +#endif +#if( !defined( require_string ) ) + #define require_string( X, LABEL, STR ) \ + do \ + { \ + if( !( X ) ) \ + { \ + debug_print_assert( 0, #X, STR, __FILE__, __LINE__, __ROUTINE__ ); \ + goto LABEL; \ + } \ + \ + } while( 0 ) +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined require_quiet + + @abstract Requires that an expression evaluate to true. + + @discussion + + If expression evalulates to false, this jumps to a label. No debugging information is printed. +*/ + +#if( DEBUG_OVERRIDE_APPLE_MACROS ) + #undef require_quiet +#endif +#if( !defined( require_quiet ) ) + #define require_quiet( X, LABEL ) \ + do \ + { \ + if( !( X ) ) \ + { \ + goto LABEL; \ + } \ + \ + } while( 0 ) +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined require_noerr + + @abstract Require that an error code is noErr (0). + + @discussion + + If the error code is non-0, this prints debugging information (actual expression string, file, line number, + function name, etc.) using the default debugging output method then jumps to a label. +*/ + +#if( DEBUG_OVERRIDE_APPLE_MACROS ) + #undef require_noerr +#endif +#if( !defined( require_noerr ) ) + #define require_noerr( ERR, LABEL ) \ + do \ + { \ + int_least32_t localErr; \ + \ + localErr = (int_least32_t)( ERR ); \ + if( localErr != 0 ) \ + { \ + debug_print_assert( localErr, NULL, NULL, __FILE__, __LINE__, __ROUTINE__ ); \ + goto LABEL; \ + } \ + \ + } while( 0 ) +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined require_noerr_string + + @abstract Require that an error code is noErr (0). + + @discussion + + If the error code is non-0, this prints debugging information (actual expression string, file, line number, + function name, etc.), and a custom explanation string using the default debugging output method using the + default debugging output method then jumps to a label. +*/ + +#if( DEBUG_OVERRIDE_APPLE_MACROS ) + #undef require_noerr_string +#endif +#if( !defined( require_noerr_string ) ) + #define require_noerr_string( ERR, LABEL, STR ) \ + do \ + { \ + int_least32_t localErr; \ + \ + localErr = (int_least32_t)( ERR ); \ + if( localErr != 0 ) \ + { \ + debug_print_assert( localErr, NULL, STR, __FILE__, __LINE__, __ROUTINE__ ); \ + goto LABEL; \ + } \ + \ + } while( 0 ) +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined require_noerr_action_string + + @abstract Require that an error code is noErr (0). + + @discussion + + If the error code is non-0, this prints debugging information (actual expression string, file, line number, + function name, etc.), and a custom explanation string using the default debugging output method using the + default debugging output method then executes an action and jumps to a label. +*/ + +#if( DEBUG_OVERRIDE_APPLE_MACROS ) + #undef require_noerr_action_string +#endif +#if( !defined( require_noerr_action_string ) ) + #define require_noerr_action_string( ERR, LABEL, ACTION, STR ) \ + do \ + { \ + int_least32_t localErr; \ + \ + localErr = (int_least32_t)( ERR ); \ + if( localErr != 0 ) \ + { \ + debug_print_assert( localErr, NULL, STR, __FILE__, __LINE__, __ROUTINE__ ); \ + { ACTION; } \ + goto LABEL; \ + } \ + \ + } while( 0 ) +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined require_noerr_quiet + + @abstract Require that an error code is noErr (0). + + @discussion + + If the error code is non-0, this jumps to a label. No debugging information is printed. +*/ + +#if( DEBUG_OVERRIDE_APPLE_MACROS ) + #undef require_noerr_quiet +#endif +#if( !defined( require_noerr_quiet ) ) + #define require_noerr_quiet( ERR, LABEL ) \ + do \ + { \ + if( ( ERR ) != 0 ) \ + { \ + goto LABEL; \ + } \ + \ + } while( 0 ) +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined require_noerr_action + + @abstract Require that an error code is noErr (0) with an action to execute otherwise. + + @discussion + + If the error code is non-0, this prints debugging information (actual expression string, file, line number, + function name, etc.) using the default debugging output method then executes an action and jumps to a label. +*/ + +#if( DEBUG_OVERRIDE_APPLE_MACROS ) + #undef require_noerr_action +#endif +#if( !defined( require_noerr_action ) ) + #define require_noerr_action( ERR, LABEL, ACTION ) \ + do \ + { \ + int_least32_t localErr; \ + \ + localErr = (int_least32_t)( ERR ); \ + if( localErr != 0 ) \ + { \ + debug_print_assert( localErr, NULL, NULL, __FILE__, __LINE__, __ROUTINE__ ); \ + { ACTION; } \ + goto LABEL; \ + } \ + \ + } while( 0 ) +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined require_noerr_action_quiet + + @abstract Require that an error code is noErr (0) with an action to execute otherwise. + + @discussion + + If the error code is non-0, this executes an action and jumps to a label. No debugging information is printed. +*/ + +#if( DEBUG_OVERRIDE_APPLE_MACROS ) + #undef require_noerr_action_quiet +#endif +#if( !defined( require_noerr_action_quiet ) ) + #define require_noerr_action_quiet( ERR, LABEL, ACTION ) \ + do \ + { \ + if( ( ERR ) != 0 ) \ + { \ + { ACTION; } \ + goto LABEL; \ + } \ + \ + } while( 0 ) +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined require_action + + @abstract Requires that an expression evaluate to true with an action to execute otherwise. + + @discussion + + If expression evalulates to false, this prints debugging information (actual expression string, file, line number, + function name, etc.) using the default debugging output method then executes an action and jumps to a label. +*/ + +#if( DEBUG_OVERRIDE_APPLE_MACROS ) + #undef require_action +#endif +#if( !defined( require_action ) ) + #define require_action( X, LABEL, ACTION ) \ + do \ + { \ + if( !( X ) ) \ + { \ + debug_print_assert( 0, #X, NULL, __FILE__, __LINE__, __ROUTINE__ ); \ + { ACTION; } \ + goto LABEL; \ + } \ + \ + } while( 0 ) +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined require_action_quiet + + @abstract Requires that an expression evaluate to true with an action to execute otherwise. + + @discussion + + If expression evalulates to false, this executes an action and jumps to a label. No debugging information is printed. +*/ + +#if( DEBUG_OVERRIDE_APPLE_MACROS ) + #undef require_action_quiet +#endif +#if( !defined( require_action_quiet ) ) + #define require_action_quiet( X, LABEL, ACTION ) \ + do \ + { \ + if( !( X ) ) \ + { \ + { ACTION; } \ + goto LABEL; \ + } \ + \ + } while( 0 ) +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined require_action_string + + @abstract Requires that an expression evaluate to true with an explanation and action to execute otherwise. + + @discussion + + If expression evalulates to false, this prints debugging information (actual expression string, file, line number, + function name, etc.) and a custom explanation string using the default debugging output method then executes an + action and jumps to a label. +*/ + +#if( DEBUG_OVERRIDE_APPLE_MACROS ) + #undef require_action_string +#endif +#if( !defined( require_action_string ) ) + #define require_action_string( X, LABEL, ACTION, STR ) \ + do \ + { \ + if( !( X ) ) \ + { \ + debug_print_assert( 0, #X, STR, __FILE__, __LINE__, __ROUTINE__ ); \ + { ACTION; } \ + goto LABEL; \ + } \ + \ + } while( 0 ) + +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined require_throw + + @abstract Requires that an expression evaluates to true or an exception is thrown. + + @discussion + + If the expression evaluates to false, this prints debugging information (actual expression string, file, + line number, function name, etc.) using the default debugging output method then throws an exception. +*/ + +#if( defined( __cplusplus ) ) + #define require_throw( X ) \ + do \ + { \ + if( !( X ) ) \ + { \ + debug_print_assert( 0, #X, NULL, __FILE__, __LINE__, __ROUTINE__ ); \ + throw kUnknownErr; \ + } \ + \ + } while( 0 ) +#endif + +#if 0 +#pragma mark == Design-By-Contract macros == +#endif + +//=========================================================================================================================== +// Design-By-Contract macros +//=========================================================================================================================== + +#define ensure( X ) check( X ) +#define ensure_string( X, STR ) check_string( X, STR ) +#define ensure_noerr( ERR ) check_noerr( ERR ) +#define ensure_noerr_string( ERR, STR ) check_noerr_string( ERR, STR ) +#define ensure_translated_errno( TEST, ERRNO, ALTERNATE_ERROR ) check_translated_errno( TEST, ERRNO, ALTERNATE_ERROR ) + +// Note: Design-By-Contract "require" macros are already defined elsewhere. + +#if 0 +#pragma mark == Expect macros == +#endif + +//=========================================================================================================================== +// Expect macros +//=========================================================================================================================== + +// Expect macros allow code to include runtime checking of things that should not happen in shipping code (e.g. internal +// programmer errors, such as a NULL parameter where it is not allowed). Once the code has been verified to work correctly +// without asserting, the DEBUG_EXPECT_VERIFIED conditional can be set to eliminate the error checking entirely. It can +// also be useful to measure the cost of error checking code by profiling with it enable and with it disabled. + +#if( DEBUG_EXPECT_VERIFIED ) + #define require_expect + #define require_string_expect + #define require_quiet_expect + #define require_noerr_expect + #define require_noerr_string_expect + #define require_noerr_action_string_expect + #define require_noerr_quiet_expect + #define require_noerr_action_expect + #define require_noerr_action_quiet_expect + #define require_action_expect + #define require_action_quiet_expect + #define require_action_string_expect +#else + #define require_expect require + #define require_string_expect require_string + #define require_quiet_expect require_quiet + #define require_noerr_expect require_noerr + #define require_noerr_string_expect require_noerr_string + #define require_noerr_action_string_expect require_noerr_action_string + #define require_noerr_quiet_expect require_noerr_quiet + #define require_noerr_action_expect require_noerr_action + #define require_noerr_action_quiet_expect require_noerr_action_quiet + #define require_action_expect require_action + #define require_action_quiet_expect require_action_quiet + #define require_action_string_expect require_action_string +#endif + +#if 0 +#pragma mark == Output macros == +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined debug_string + + @abstract Prints a debugging C string. +*/ + +#if( DEBUG_OVERRIDE_APPLE_MACROS ) + #undef debug_string +#endif +#if( !defined( debug_string ) ) + #if( DEBUG ) + #define debug_string( STR ) \ + do \ + { \ + debug_print_assert( 0, NULL, STR, __FILE__, __LINE__, __ROUTINE__ ); \ + \ + } while( 0 ) + #else + #define debug_string( STR ) + #endif +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined debug_print_assert + + @abstract Prints an assertion. +*/ + +#if( DEBUG ) + #define debug_print_assert( ERROR_CODE, ASSERT_STRING, MESSAGE, FILENAME, LINE_NUMBER, FUNCTION ) \ + DebugPrintAssert( ERROR_CODE, ASSERT_STRING, MESSAGE, FILENAME, LINE_NUMBER, FUNCTION ) +#else + #define debug_print_assert( ERROR_CODE, ASSERT_STRING, MESSAGE, FILENAME, LINE_NUMBER, FUNCTION ) +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined dlog + + @abstract Prints a debug-only message. +*/ + +#if( DEBUG ) + #if( DEBUG_C99_VA_ARGS ) + #define dlog( ... ) DebugPrintF( __VA_ARGS__ ) + #elif( DEBUG_GNU_VA_ARGS ) + #define dlog( ARGS... ) DebugPrintF( ## ARGS ) + #else + #define dlog DebugPrintF + #endif +#else + #if( DEBUG_C99_VA_ARGS ) + #define dlog( ... ) + #elif( DEBUG_GNU_VA_ARGS ) + #define dlog( ARGS... ) + #else + #define dlog while( 0 ) + #endif +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined dlogv + + @abstract Prints a debug-only message. +*/ + +#if( DEBUG ) + #define dlogv( LEVEL, FORMAT, LIST ) DebugPrintFVAList( ( LEVEL ), ( FORMAT ), ( LIST ) ) +#else + #define dlogv( LEVEL, FORMAT, LIST ) +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined dlogmem + + @abstract Prints a debug-only dump of memory. +*/ + +#if( DEBUG ) + #define dlogmem( LEVEL, PTR, SIZE ) \ + DebugHexDump( ( LEVEL ), 0, NULL, 0, 0, NULL, 0, ( PTR ), ( PTR ), ( SIZE ), kDebugFlagsNone, NULL, 0 ) +#else + #define dlogmem( LEVEL, PTR, SIZE ) +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined DebugNSLog + + @abstract Debug-only macro for the Cocoa NSLog function. +*/ + +#if( DEBUG ) + #if( DEBUG_C99_VA_ARGS ) + #define DebugNSLog( ... ) NSLog( __VA_ARGS__ ) + #elif( DEBUG_GNU_VA_ARGS ) + #define DebugNSLog( ARGS... ) NSLog( ## ARGS ) + #else + #define DebugNSLog NSLog + #endif +#else + #if( DEBUG_C99_VA_ARGS ) + #define DebugNSLog( ... ) + #elif( DEBUG_GNU_VA_ARGS ) + #define DebugNSLog( ARGS... ) + #else + #define DebugNSLog while( 0 ) + #endif +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @defined DebugLogMsg + + @abstract Debug-only macro for the VxWorks logMsg function. +*/ + +#if( TARGET_OS_VXWORKS ) + #if( DEBUG ) + #define DebugLogMsg( LEVEL, FORMAT, P1, P2, P3, P4, P5, P6 ) \ + do \ + { \ + if( ( inLevel >= gDebugPrintLevelMin ) || ( inLevel <= gDebugPrintLevelMax ) ) \ + { \ + logMsg( ( FORMAT ), ( P1 ), ( P2 ), ( P3 ), ( P4 ), ( P5 ), ( P6 ) ); \ + } \ + \ + } while( 0 ) + #else + #define DebugLogMsg( LEVEL, FORMAT, P1, P2, P3, P4, P5, P6 ) + #endif +#else + #define DebugLogMsg dlog +#endif + +#if 0 +#pragma mark == Routines - General == +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @function DebugInitialize + + @abstract Initializes the debugging library for a specific kind of output. + + @param inType + @param varArg Variable number parameters, controlled by the "inType" parameter. +*/ + +#if( DEBUG ) + DEBUG_EXPORT OSStatus DebugInitialize( DebugOutputType inType, ... ); +#endif + +#if( DEBUG ) + #if( DEBUG_C99_VA_ARGS ) + #define debug_initialize( ... ) DebugInitialize( __VA_ARGS__ ) + #elif( DEBUG_GNU_VA_ARGS ) + #define debug_initialize( ARGS... ) DebugInitialize( ## ARGS ) + #else + #define debug_initialize DebugInitialize + #endif +#else + #if( DEBUG_C99_VA_ARGS ) + #define debug_initialize( ... ) + #elif( DEBUG_GNU_VA_ARGS ) + #define debug_initialize( ARGS... ) + #else + #define debug_initialize while( 0 ) + #endif +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @function DebugFinalize + + @abstract Releases any resources used by the debugging library +*/ + +#if( DEBUG ) + DEBUG_EXPORT void DebugFinalize( void ); +#endif + +#if( DEBUG ) + #define debug_terminate() DebugFinalize() +#else + #define debug_terminate() +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @function DebugGetProperty + + @abstract Gets the specified property from the debugging library. +*/ + +#if( DEBUG ) + DEBUG_EXPORT OSStatus DebugGetProperty( DebugPropertyTag inTag, ... ); +#endif + +#if( DEBUG ) + #if( DEBUG_C99_VA_ARGS ) + #define debug_get_property( ... ) DebugGetProperty( __VA_ARGS__ ) + #elif( DEBUG_GNU_VA_ARGS ) + #define debug_get_property( ARGS... ) DebugGetProperty( ## ARGS ) + #else + #define debug_get_property DebugGetProperty + #endif +#else + #if( DEBUG_C99_VA_ARGS ) + #define debug_get_property( ... ) + #elif( DEBUG_GNU_VA_ARGS ) + #define debug_get_property( ARGS... ) + #else + #define debug_get_property while( 0 ) + #endif +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @function DebugSetProperty + + @abstract Sets the specified property from the debugging library. +*/ + +#if( DEBUG ) + DEBUG_EXPORT OSStatus DebugSetProperty( DebugPropertyTag inTag, ... ); +#endif + +#if( DEBUG ) + #if( DEBUG_C99_VA_ARGS ) + #define debug_set_property( ... ) DebugSetProperty( __VA_ARGS__ ) + #elif( DEBUG_GNU_VA_ARGS ) + #define debug_set_property( ARGS... ) DebugSetProperty( ## ARGS ) + #else + #define debug_set_property DebugSetProperty + #endif +#else + #if( DEBUG_C99_VA_ARGS ) + #define debug_set_property( ... ) + #elif( DEBUG_GNU_VA_ARGS ) + #define debug_set_property( ARGS... ) + #else + #define debug_set_property while( 0 ) + #endif +#endif + +#if 0 +#pragma mark == Routines - Debugging Output == +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @function DebugPrintF + + @abstract Prints a debug message with printf-style formatting. + + @param inLevel Error that generated this assert or noErr. + + @param inFormatString + C string containing assertion text. + + @param VAR_ARG + Variable number of arguments depending on the format string. + + @result Number of bytes printed or -1 on error. +*/ + +#if( DEBUG ) + DEBUG_EXPORT size_t DebugPrintF( DebugLevel inLevel, const char *inFormat, ... ); +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @function DebugPrintFVAList + + @abstract va_list version of DebugPrintF. See DebugPrintF for more info. +*/ + +#if( DEBUG ) + DEBUG_EXPORT size_t DebugPrintFVAList( DebugLevel inLevel, const char *inFormat, va_list inArgs ); +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @function DebugPrintAssert + + @abstract Prints a message describing the reason the (e.g. an assert failed), an optional error message, + an optional source filename, an optional source line number. + + @param inErrorCode Error that generated this assert or noErr. + @param inAssertString C string containing assertion text. + @param inMessage C string containing a message about the assert. + @param inFileName C string containing path of file where the error occurred. + @param inLineNumber Line number in source file where the error occurred. + @param inFunction C string containing name of function where assert occurred. + + @discussion + + Example output: + + [ASSERT] assert: "dataPtr != NULL" allocate memory for object failed + [ASSERT] where: "MyFile.c", line 123, ("MyFunction") + + OR + + [ASSERT] error: -6728 (kNoMemoryErr) + [ASSERT] where: "MyFile.c", line 123, ("MyFunction") +*/ + +#if( DEBUG ) + DEBUG_EXPORT void + DebugPrintAssert( + int_least32_t inErrorCode, + const char * inAssertString, + const char * inMessage, + const char * inFilename, + int_least32_t inLineNumber, + const char * inFunction ); +#endif + +#if 0 +#pragma mark == Routines - Utilities == +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @function DebugSNPrintF + + @abstract Debugging versions of standard C snprintf with extra features. + + @param sbuffer Buffer to receive result. Null terminated unless the buffer size is 0. + @param buflen Size of the buffer including space for the null terminator. + @param fmt printf-style format string. + @param VAR_ARG Variable number of arguments depending on the format string. + + @result Number of characters written (minus the null terminator). + + @discussion + + Extra features over the standard C snprintf: +
+		64-bit support for %d (%lld), %i (%lli), %u (%llu), %o (%llo), %x (%llx), and %b (%llb).
+		%@   - Cocoa/CoreFoundation object. Param is the object. Strings are used directly. Others use CFCopyDescription.
+		%a   - Network Address: %.4a=IPv4, %.6a=Ethernet, %.8a Fibre Channel, %.16a=IPv6. Arg=ptr to network address.
+		%#a  - IPv4 or IPv6 mDNSAddr. Arg=ptr to mDNSAddr.
+		%##a - IPv4 (if AF_INET defined) or IPv6 (if AF_INET6 defined) sockaddr. Arg=ptr to sockaddr.
+		%b   - Binary representation of integer (e.g. 01101011). Modifiers and arg=the same as %d, %x, etc.
+		%C   - Mac-style FourCharCode (e.g. 'APPL'). Arg=32-bit value to print as a Mac-style FourCharCode.
+		%H   - Hex Dump (e.g. "\x6b\xa7" -> "6B A7"). 1st arg=ptr, 2nd arg=size, 3rd arg=max size.
+		%#H  - Hex Dump & ASCII (e.g. "\x41\x62" -> "6B A7 'Ab'"). 1st arg=ptr, 2nd arg=size, 3rd arg=max size.
+		%m   - Error Message (e.g. 0 -> "kNoErr"). Modifiers and error code arg=the same as %d, %x, etc.
+		%#s  - Pascal-style length-prefixed string. Arg=ptr to string.
+		%##s - DNS label-sequence name. Arg=ptr to name.
+		%S   - UTF-16 string, 0x0000 terminated. Host order if no BOM. Precision is UTF-16 count. Precision includes BOM.
+		%#S  - Big Endian UTF-16 string (unless BOM overrides). Otherwise, the same as %S.
+		%##S - Little Endian UTF-16 string (unless BOM overrides). Otherwise, the same as %S.
+		%U   - Universally Unique Identifier (UUID) (e.g. 6ba7b810-9dad-11d1-80b4-00c04fd430c8). Arg=ptr to 16-byte UUID.
+	
+*/ + +#if( DEBUG ) + DEBUG_EXPORT size_t DebugSNPrintF(char *sbuffer, size_t buflen, const char *fmt, ...); +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @function DebugSNPrintFVAList + + @abstract va_list version of DebugSNPrintF. See DebugSNPrintF for more info. +*/ + +#if( DEBUG ) + DEBUG_EXPORT size_t DebugSNPrintFVAList(char *sbuffer, size_t buflen, const char *fmt, va_list arg); +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @function DebugGetErrorString + + @abstract Gets an error string from an error code. + + @param inStatus Error code to get the string for. + @param inBuffer Optional buffer to copy the string to for non-static strings. May be null. + @param inBufferSize Size of optional buffer. May be 0. + + @result C string containing error string for the error code. Guaranteed to be a valid, static string. If a + buffer is supplied, the return value will always be a pointer to the supplied buffer, which will + contain the best available description of the error code. If a buffer is not supplied, the return + value will be the best available description of the error code that can be represented as a static + string. This allows code that cannot use a temporary buffer to hold the result to still get a useful + error string in most cases, but also allows code that can use a temporary buffer to get the best + available description. +*/ + +#if( DEBUG ) + DEBUG_EXPORT const char * DebugGetErrorString( int_least32_t inErrorCode, char *inBuffer, size_t inBufferSize ); +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @function DebugHexDump + + @abstract Hex dumps data to a string or to the output device. +*/ + +#if( DEBUG ) + DEBUG_EXPORT size_t + DebugHexDump( + DebugLevel inLevel, + int inIndent, + const char * inLabel, + size_t inLabelSize, + int inLabelMinWidth, + const char * inType, + size_t inTypeSize, + const void * inDataStart, + const void * inData, + size_t inDataSize, + DebugFlags inFlags, + char * outBuffer, + size_t inBufferSize ); +#endif + +#if( DEBUG ) + #define dloghex( LEVEL, INDENT, LABEL, LABEL_SIZE, LABEL_MIN_SIZE, TYPE, TYPE_SIZE, DATA_START, DATA, DATA_SIZE, FLAGS, BUFFER, BUFFER_SIZE ) \ + DebugHexDump( ( LEVEL ), (INDENT), ( LABEL ), ( LABEL_SIZE ), ( LABEL_MIN_SIZE ), ( TYPE ), ( TYPE_SIZE ), \ + ( DATA_START ), ( DATA ), ( DATA_SIZE ), ( FLAGS ), ( BUFFER ), ( BUFFER_SIZE ) ) +#else + #define dloghex( LEVEL, INDENT, LABEL, LABEL_SIZE, LABEL_MIN_SIZE, TYPE, TYPE_SIZE, DATA_START, DATA, DATA_SIZE, FLAGS, BUFFER, BUFFER_SIZE ) +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @function DebugTaskLevel + + @abstract Returns the current task level. + + @result Current task level + + @discussion + + Bit masks to isolate portions of the result (note that some masks may also need bit shifts to right justify): +
+		kDebugInterruptLevelMask				- Indicates the current interrupt level (> 0 means interrupt time).
+		kDebugInVBLTaskMask						- Indicates if a VBL task is currently being executed.
+		kDebugInDeferredTaskMask				- Indicates if a Deferred Task is currently being executed.
+		kDebugInSecondaryInterruptHandlerMask	- Indicates if a Secondary Interrupt Handler is currently being executed.
+		kDebugPageFaultFatalMask				- Indicates if it is unsafe to cause a page fault (worse than interrupt time).
+		kDebugMPTaskLevelMask					- Indicates if being called from an MP task.
+		kDebugInterruptDepthMask				- 0 means task level, 1 means in interrupt, > 1 means in nested interrupt.
+	
+ + Helpers: +
+		DebugExtractTaskLevelInterruptDepth()   - Macro to extract interrupt depth from task level value.
+	
+*/ + +#if( DEBUG ) + DEBUG_EXPORT uint32_t DebugTaskLevel( void ); +#endif + +//--------------------------------------------------------------------------------------------------------------------------- +/*! @function DebugServicesTest + + @abstract Unit test. +*/ + +#if( DEBUG ) + DEBUG_EXPORT OSStatus DebugServicesTest( void ); +#endif + +#ifdef __cplusplus + } +#endif + +#endif // __DEBUG_SERVICES__ diff --git a/mDNSShared/GenLinkedList.c b/mDNSShared/GenLinkedList.c index 1d231f2..d9f9033 100755 --- a/mDNSShared/GenLinkedList.c +++ b/mDNSShared/GenLinkedList.c @@ -1,24 +1,18 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ File: GenLinkedList.c @@ -30,6 +24,9 @@ Change History (most recent first): $Log: GenLinkedList.c,v $ +Revision 1.4 2006/08/14 23:24:56 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.3 2004/04/22 21:14:42 cheshire Fix comment spelling mistake diff --git a/mDNSShared/GenLinkedList.h b/mDNSShared/GenLinkedList.h index 5a7de91..4df6e67 100755 --- a/mDNSShared/GenLinkedList.h +++ b/mDNSShared/GenLinkedList.h @@ -1,24 +1,18 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ File: GenLinkedList.c @@ -30,6 +24,9 @@ Change History (most recent first): $Log: GenLinkedList.h,v $ +Revision 1.3 2006/08/14 23:24:56 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.2 2004/02/05 07:41:08 cheshire Add Log header diff --git a/mDNSShared/Java/BaseListener.java b/mDNSShared/Java/BaseListener.java index 665263d..85e9d02 100644 --- a/mDNSShared/Java/BaseListener.java +++ b/mDNSShared/Java/BaseListener.java @@ -1,28 +1,25 @@ -/* +/* -*- Mode: Java; tab-width: 4 -*- + * * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: BaseListener.java,v $ +Revision 1.3 2006/08/14 23:25:08 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.2 2004/04/30 21:48:27 rpantos Change line endings for CVS. diff --git a/mDNSShared/Java/BrowseListener.java b/mDNSShared/Java/BrowseListener.java index 5bda3ae..b254c97 100644 --- a/mDNSShared/Java/BrowseListener.java +++ b/mDNSShared/Java/BrowseListener.java @@ -1,28 +1,25 @@ -/* +/* -*- Mode: Java; tab-width: 4 -*- + * * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: BrowseListener.java,v $ +Revision 1.3 2006/08/14 23:25:08 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.2 2004/04/30 21:48:27 rpantos Change line endings for CVS. diff --git a/mDNSShared/Java/DNSRecord.java b/mDNSShared/Java/DNSRecord.java index 73e1626..5050a7a 100644 --- a/mDNSShared/Java/DNSRecord.java +++ b/mDNSShared/Java/DNSRecord.java @@ -1,28 +1,25 @@ -/* +/* -*- Mode: Java; tab-width: 4 -*- + * * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: DNSRecord.java,v $ +Revision 1.3 2006/08/14 23:25:08 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.2 2004/12/11 03:00:59 rpantos Java DNSRecord API should be cleaned up diff --git a/mDNSShared/Java/DNSSD.java b/mDNSShared/Java/DNSSD.java index 50d29e4..a431df1 100644 --- a/mDNSShared/Java/DNSSD.java +++ b/mDNSShared/Java/DNSSD.java @@ -1,28 +1,28 @@ -/* +/* -*- Mode: Java; tab-width: 4 -*- + * * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: DNSSD.java,v $ +Revision 1.11 2006/08/14 23:25:08 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + +Revision 1.10 2006/06/20 23:05:55 rpantos + Java needs to implement DNSServiceRegisterRecord equivalent + Revision 1.9 2005/10/26 01:52:24 cheshire Race condition in Java code (doesn't work at all on Linux) @@ -54,10 +54,6 @@ First checked in. This file declares and implements DNSSD, the central Java factory class for doing DNS Service Discovery. It includes the mostly-abstract public interface, as well as the Apple* implementation subclasses. - - To do: - - implement network interface mappings - - RegisterRecord */ @@ -310,6 +306,18 @@ abstract public class DNSSD throws DNSSDException { return register( 0, 0, serviceName, regType, null, null, port, null, listener); } + /** Create a {@link DNSSDRecordRegistrar} allowing efficient registration of + multiple individual records.

+

+ @return A {@link DNSSDRecordRegistrar} that can be used to register records. + + @throws SecurityException If a security manager is present and denies RuntimePermission("getDNSSDInstance"). + @see RuntimePermission + */ + public static DNSSDRecordRegistrar createRecordRegistrar( RegisterRecordListener listener) + throws DNSSDException + { return getInstance()._createRecordRegistrar( listener); } + /** Query for an arbitrary DNS record.

@param flags Possible values are: MORE_COMING. @@ -474,6 +482,9 @@ abstract public class DNSSD String domain, String host, int port, TXTRecord txtRecord, RegisterListener listener) throws DNSSDException; + abstract protected DNSSDRecordRegistrar _createRecordRegistrar( RegisterRecordListener listener) + throws DNSSDException; + abstract protected DNSSDService _queryRecord( int flags, int ifIndex, String serviceName, int rrtype, int rrclass, QueryListener listener) throws DNSSDException; @@ -595,6 +606,12 @@ class AppleDNSSD extends DNSSD ( txtRecord != null) ? txtRecord.getRawBytes() : null, client); } + protected DNSSDRecordRegistrar _createRecordRegistrar( RegisterRecordListener listener) + throws DNSSDException + { + return new AppleRecordRegistrar( listener); + } + protected DNSSDService _queryRecord( int flags, int ifIndex, String serviceName, int rrtype, int rrclass, QueryListener client) throws DNSSDException @@ -797,7 +814,6 @@ class AppleRegistration extends AppleService implements DNSSDRegistration AppleDNSRecord newRecord = new AppleDNSRecord( this); this.ThrowOnErr( this.AddRecord( flags, rrType, rData, ttl, newRecord)); - return newRecord; } @@ -815,6 +831,35 @@ class AppleRegistration extends AppleService implements DNSSDRegistration protected native int AddRecord( int flags, int rrType, byte[] rData, int ttl, AppleDNSRecord destObj); } +class AppleRecordRegistrar extends AppleService implements DNSSDRecordRegistrar +{ + public AppleRecordRegistrar( RegisterRecordListener listener) + throws DNSSDException + { + super(listener); + this.ThrowOnErr( this.CreateConnection()); + if ( !AppleDNSSD.hasAutoCallbacks) + new Thread(this).start(); + } + + public DNSRecord registerRecord( int flags, int ifIndex, String fullname, int rrtype, + int rrclass, byte[] rdata, int ttl) + throws DNSSDException + { + AppleDNSRecord newRecord = new AppleDNSRecord( this); + + this.ThrowOnErr( this.RegisterRecord( flags, ifIndex, fullname, rrtype, rrclass, rdata, ttl, newRecord)); + return newRecord; + } + + // Sets fNativeContext. Returns non-zero on error. + protected native int CreateConnection(); + + // Sets fNativeContext. Returns non-zero on error. + protected native int RegisterRecord( int flags, int ifIndex, String fullname, int rrtype, + int rrclass, byte[] rdata, int ttl, AppleDNSRecord destObj); +} + class AppleQuery extends AppleService { public AppleQuery( int flags, int ifIndex, String serviceName, int rrtype, diff --git a/mDNSShared/Java/DNSSDException.java b/mDNSShared/Java/DNSSDException.java index 0ab0587..f73afea 100644 --- a/mDNSShared/Java/DNSSDException.java +++ b/mDNSShared/Java/DNSSDException.java @@ -1,28 +1,25 @@ -/* +/* -*- Mode: Java; tab-width: 4 -*- + * * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: DNSSDException.java,v $ +Revision 1.4 2006/08/14 23:25:08 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.3 2005/07/10 22:19:01 cheshire Add missing error codes to list of public static final ints diff --git a/mDNSShared/Java/DNSSDRecordRegistrar.java b/mDNSShared/Java/DNSSDRecordRegistrar.java new file mode 100644 index 0000000..825634f --- /dev/null +++ b/mDNSShared/Java/DNSSDRecordRegistrar.java @@ -0,0 +1,77 @@ +/* -*- Mode: Java; tab-width: 4 -*- + * + * Copyright (c) 2006 Apple Computer, Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + + This file declares the public interface to DNSSDRecordRegistrar, a DNSSDService + subclass that allows efficient registration of multiple individual records. + + Change History (most recent first): + +$Log: DNSSDRecordRegistrar.java,v $ +Revision 1.2 2006/08/14 23:25:08 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + +Revision 1.1 2006/06/20 23:00:12 rpantos + Java needs to implement DNSServiceRegisterRecord equivalent + + */ + + +package com.apple.dnssd; + + +/** An object for registering records, created by {@link DNSSD#createRecordRegistrar}. */ + +public interface DNSSDRecordRegistrar extends DNSSDService +{ + /** Register an independent {@link DNSRecord}.

+ @param flags + Possible values are SHARED or UNIQUE (see flag type definitions for details). +

+ @param ifIndex + If non-zero, specifies the interface on which to register the record + (the index for a given interface is determined via the if_nametoindex() + family of calls.) Passing 0 causes the record to be registered on all interfaces. +

+ @param fullname + The full domain name of the resource record. +

+ @param rrtype + The numerical type of the resource record to be queried for (e.g. PTR, SRV, etc) + as defined in nameser.h. +

+ @param rrclass + The class of the resource record, as defined in nameser.h + (usually 1 for the Internet class). +

+ @param rData + The new rdata as it is to appear in the DNS record. +

+ @param ttl + The time to live of the resource record, in seconds. Pass 0 to use a default value. +

+ @param listener + This object will get called when the service is registered. +

+ @return A {@link DNSSDService} that can be used to abort the record registration. + + @throws SecurityException If a security manager is present and denies RuntimePermission("getDNSSDInstance"). + @see RuntimePermission + */ + public DNSRecord registerRecord( int flags, int ifIndex, String fullname, int rrtype, + int rrclass, byte[] rdata, int ttl) + throws DNSSDException; +} + diff --git a/mDNSShared/Java/DNSSDRegistration.java b/mDNSShared/Java/DNSSDRegistration.java index 4a4942f..86f2d83 100644 --- a/mDNSShared/Java/DNSSDRegistration.java +++ b/mDNSShared/Java/DNSSDRegistration.java @@ -1,28 +1,25 @@ -/* +/* -*- Mode: Java; tab-width: 4 -*- + * * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: DNSSDRegistration.java,v $ +Revision 1.3 2006/08/14 23:25:08 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.2 2004/12/11 03:01:00 rpantos Java DNSRecord API should be cleaned up diff --git a/mDNSShared/Java/DNSSDService.java b/mDNSShared/Java/DNSSDService.java index 9868372..d5a8a38 100644 --- a/mDNSShared/Java/DNSSDService.java +++ b/mDNSShared/Java/DNSSDService.java @@ -1,28 +1,25 @@ -/* +/* -*- Mode: Java; tab-width: 4 -*- + * * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: DNSSDService.java,v $ +Revision 1.3 2006/08/14 23:25:08 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.2 2004/04/30 21:48:27 rpantos Change line endings for CVS. diff --git a/mDNSShared/Java/DomainListener.java b/mDNSShared/Java/DomainListener.java index bfb319a..233c188 100644 --- a/mDNSShared/Java/DomainListener.java +++ b/mDNSShared/Java/DomainListener.java @@ -1,28 +1,25 @@ -/* +/* -*- Mode: Java; tab-width: 4 -*- + * * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: DomainListener.java,v $ +Revision 1.3 2006/08/14 23:25:08 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.2 2004/04/30 21:48:27 rpantos Change line endings for CVS. diff --git a/mDNSShared/Java/JNISupport.c b/mDNSShared/Java/JNISupport.c index d7c6243..bd40fb9 100644 --- a/mDNSShared/Java/JNISupport.c +++ b/mDNSShared/Java/JNISupport.c @@ -1,28 +1,34 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: JNISupport.c,v $ +Revision 1.17 2006/08/14 23:25:08 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + +Revision 1.16 2006/07/14 02:35:47 cheshire +Added (commented out) syslog debugging messages + +Revision 1.15 2006/06/27 19:34:43 cheshire + txtRecord parameter of DNSServiceResolveReply() should be unsigned char * + +Revision 1.14 2006/06/20 23:03:35 rpantos + Java needs to implement DNSServiceRegisterRecord equivalent + Revision 1.13 2005/10/26 01:52:24 cheshire Race condition in Java code (doesn't work at all on Linux) @@ -108,6 +114,8 @@ static DWORD if_nametoindex( const char * nameStr ); #include "DNSSD.java.h" +//#include + // convenience definition #ifdef __GNUC__ #define _UNUSED __attribute__ ((unused)) @@ -416,7 +424,7 @@ JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleBrowser_CreateBrowser( JNIEnv * static void DNSSD_API ServiceResolveReply( DNSServiceRef sdRef _UNUSED, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *fullname, const char *hosttarget, - uint16_t port, uint16_t txtLen, const char *txtRecord, void *context) + uint16_t port, uint16_t txtLen, const unsigned char *txtRecord, void *context) { OpContext *pContext = (OpContext*) context; jclass txtCls; @@ -527,6 +535,7 @@ JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleRegistration_BeginRegister( JNI jint ifIndex, jint flags, jstring serviceName, jstring regType, jstring domain, jstring host, jint port, jbyteArray txtRecord) { + //syslog(LOG_ERR, "BR"); jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis); jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "I"); OpContext *pContext = NULL; @@ -534,6 +543,8 @@ JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleRegistration_BeginRegister( JNI jbyte *pBytes; jsize numBytes; + //syslog(LOG_ERR, "BR: contextField %d", contextField); + if ( contextField != 0) pContext = NewContext( pEnv, pThis, "serviceRegistered", "(Lcom/apple/dnssd/DNSSDRegistration;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); @@ -547,6 +558,8 @@ JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleRegistration_BeginRegister( JNI const char *domainStr = SafeGetUTFChars( pEnv, domain); const char *hostStr = SafeGetUTFChars( pEnv, host); + //syslog(LOG_ERR, "BR: regStr %s", regStr); + // Since Java ints are defined to be big-endian, we de-canonicalize 'port' from a // big-endian number into a 16-bit pattern here. uint16_t portBits = port; @@ -674,6 +687,119 @@ JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDNSRecord_Remove( JNIEnv *pEnv, } +JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleRecordRegistrar_CreateConnection( JNIEnv *pEnv, jobject pThis) +{ + jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis); + jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "I"); + OpContext *pContext = NULL; + DNSServiceErrorType err = kDNSServiceErr_NoError; + + if ( contextField != 0) + pContext = NewContext( pEnv, pThis, "recordRegistered", "(Lcom/apple/dnssd/DNSRecord;I)V"); + else + err = kDNSServiceErr_BadParam; + + if ( pContext != NULL) + { + err = DNSServiceCreateConnection( &pContext->ServiceRef); + if ( err == kDNSServiceErr_NoError) + { + (*pEnv)->SetIntField( pEnv, pThis, contextField, (jint) pContext); + } + } + else + err = kDNSServiceErr_NoMemory; + + return err; +} + +struct RecordRegistrationRef +{ + OpContext *Context; + jobject RecordObj; +}; +typedef struct RecordRegistrationRef RecordRegistrationRef; + +static void DNSSD_API RegisterRecordReply( DNSServiceRef sdRef _UNUSED, + DNSRecordRef recordRef _UNUSED, DNSServiceFlags flags, + DNSServiceErrorType errorCode, void *context) +{ + RecordRegistrationRef *regEnvelope = (RecordRegistrationRef*) context; + OpContext *pContext = regEnvelope->Context; + + SetupCallbackState( &pContext->Env); + + if ( pContext->ClientObj != NULL && pContext->Callback != NULL) + { + if ( errorCode == kDNSServiceErr_NoError) + { + (*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj, pContext->Callback, + regEnvelope->RecordObj, flags); + } + else + ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode); + } + + (*pContext->Env)->DeleteWeakGlobalRef( pContext->Env, regEnvelope->RecordObj); + free( regEnvelope); + + TeardownCallbackState(); +} + +JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleRecordRegistrar_RegisterRecord( JNIEnv *pEnv, jobject pThis, + jint flags, jint ifIndex, jstring fullname, jint rrType, jint rrClass, + jbyteArray rData, jint ttl, jobject destObj) +{ + jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis); + jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "I"); + jclass destCls = (*pEnv)->GetObjectClass( pEnv, destObj); + jfieldID recField = (*pEnv)->GetFieldID( pEnv, destCls, "fRecord", "I"); + const char *nameStr = SafeGetUTFChars( pEnv, fullname); + OpContext *pContext = NULL; + DNSServiceErrorType err = kDNSServiceErr_NoError; + jbyte *pBytes; + jsize numBytes; + DNSRecordRef recRef; + RecordRegistrationRef *regEnvelope; + + if ( contextField != 0) + pContext = (OpContext*) (*pEnv)->GetIntField( pEnv, pThis, contextField); + if ( pContext == NULL || pContext->ServiceRef == NULL || nameStr == NULL) + return kDNSServiceErr_BadParam; + + regEnvelope = calloc( 1, sizeof *regEnvelope); + if ( regEnvelope == NULL) + return kDNSServiceErr_NoMemory; + regEnvelope->Context = pContext; + regEnvelope->RecordObj = (*pEnv)->NewWeakGlobalRef( pEnv, destObj); // must convert local ref to global to cache + + pBytes = (*pEnv)->GetByteArrayElements( pEnv, rData, NULL); + numBytes = (*pEnv)->GetArrayLength( pEnv, rData); + + err = DNSServiceRegisterRecord( pContext->ServiceRef, &recRef, flags, ifIndex, + nameStr, rrType, rrClass, numBytes, pBytes, ttl, + RegisterRecordReply, regEnvelope); + + if ( err == kDNSServiceErr_NoError) + { + (*pEnv)->SetIntField( pEnv, destObj, recField, (jint) recRef); + } + else + { + if ( regEnvelope->RecordObj != NULL) + (*pEnv)->DeleteWeakGlobalRef( pEnv, regEnvelope->RecordObj); + free( regEnvelope); + } + + if ( pBytes != NULL) + (*pEnv)->ReleaseByteArrayElements( pEnv, rData, pBytes, 0); + + SafeReleaseUTFChars( pEnv, fullname, nameStr); + + return err; +} + + static void DNSSD_API ServiceQueryReply( DNSServiceRef sdRef _UNUSED, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *serviceName, uint16_t rrtype, uint16_t rrclass, uint16_t rdlen, @@ -846,7 +972,7 @@ JNIEXPORT jstring JNICALL Java_com_apple_dnssd_AppleDNSSD_GetNameForIfIndex( JNI { char *p = LOCAL_ONLY_NAME, nameBuff[IF_NAMESIZE]; - if (ifIndex != kDNSServiceInterfaceIndexLocalOnly) + if (ifIndex != (jint) kDNSServiceInterfaceIndexLocalOnly) p = if_indextoname( ifIndex, nameBuff ); return (*pEnv)->NewStringUTF( pEnv, p); diff --git a/mDNSShared/Java/QueryListener.java b/mDNSShared/Java/QueryListener.java index 7ece74c..042798c 100644 --- a/mDNSShared/Java/QueryListener.java +++ b/mDNSShared/Java/QueryListener.java @@ -1,28 +1,25 @@ -/* +/* -*- Mode: Java; tab-width: 4 -*- + * * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: QueryListener.java,v $ +Revision 1.3 2006/08/14 23:25:08 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.2 2004/04/30 21:48:27 rpantos Change line endings for CVS. diff --git a/mDNSShared/Java/RegisterListener.java b/mDNSShared/Java/RegisterListener.java index a6cf331..ea573f0 100644 --- a/mDNSShared/Java/RegisterListener.java +++ b/mDNSShared/Java/RegisterListener.java @@ -1,28 +1,25 @@ -/* +/* -*- Mode: Java; tab-width: 4 -*- + * * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: RegisterListener.java,v $ +Revision 1.3 2006/08/14 23:25:08 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.2 2004/04/30 21:48:27 rpantos Change line endings for CVS. diff --git a/mDNSShared/Java/RegisterRecordListener.java b/mDNSShared/Java/RegisterRecordListener.java new file mode 100644 index 0000000..247e5d5 --- /dev/null +++ b/mDNSShared/Java/RegisterRecordListener.java @@ -0,0 +1,48 @@ +/* -*- Mode: Java; tab-width: 4 -*- + * + * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + + Change History (most recent first): + +$Log: RegisterRecordListener.java,v $ +Revision 1.2 2006/08/14 23:25:08 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + +Revision 1.1 2006/06/20 23:00:12 rpantos + Java needs to implement DNSServiceRegisterRecord equivalent + + + */ + + +package com.apple.dnssd; + + +/** A listener that receives results from {@link DNSSDRecordRegistrar#registerRecord}. */ + +public interface RegisterRecordListener extends BaseListener +{ + /** Called when a record registration succeeds.

+ + @param record + A {@link DNSRecord}. +

+ @param flags + Currently ignored, reserved for future use. +

+ */ + void recordRegistered( DNSRecord record, int flags); +} + diff --git a/mDNSShared/Java/ResolveListener.java b/mDNSShared/Java/ResolveListener.java index 0e21353..168edb2 100644 --- a/mDNSShared/Java/ResolveListener.java +++ b/mDNSShared/Java/ResolveListener.java @@ -1,28 +1,25 @@ -/* +/* -*- Mode: Java; tab-width: 4 -*- + * * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: ResolveListener.java,v $ +Revision 1.3 2006/08/14 23:25:08 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.2 2004/04/30 21:48:27 rpantos Change line endings for CVS. diff --git a/mDNSShared/Java/TXTRecord.java b/mDNSShared/Java/TXTRecord.java index 5eed93e..9dbe14e 100644 --- a/mDNSShared/Java/TXTRecord.java +++ b/mDNSShared/Java/TXTRecord.java @@ -1,28 +1,25 @@ -/* +/* -*- Mode: Java; tab-width: 4 -*- + * * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: TXTRecord.java,v $ +Revision 1.6 2006/08/14 23:25:08 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.5 2004/08/25 21:54:36 rpantos Fix getValue() for values containing '='. diff --git a/mDNSShared/PlatformCommon.c b/mDNSShared/PlatformCommon.c index 6ec40da..d6385b5 100644 --- a/mDNSShared/PlatformCommon.c +++ b/mDNSShared/PlatformCommon.c @@ -2,28 +2,24 @@ * * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: PlatformCommon.c,v $ +Revision 1.7 2006/08/14 23:24:56 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.6 2005/04/08 21:30:16 ksekar Compiling problems with mDNSResponder-98 on Solaris/Sparc v9 Patch submitted by Bernd Kuhls diff --git a/mDNSShared/PlatformCommon.h b/mDNSShared/PlatformCommon.h index 46a672a..ed18d85 100644 --- a/mDNSShared/PlatformCommon.h +++ b/mDNSShared/PlatformCommon.h @@ -2,28 +2,24 @@ * * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ Change History (most recent first): $Log: PlatformCommon.h,v $ +Revision 1.4 2006/08/14 23:24:56 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + Revision 1.3 2005/01/19 19:19:21 ksekar Need a way to turn off domain discovery diff --git a/mDNSShared/dns-sd.1 b/mDNSShared/dns-sd.1 index 6089ae6..0e4e2b6 100644 --- a/mDNSShared/dns-sd.1 +++ b/mDNSShared/dns-sd.1 @@ -1,25 +1,23 @@ +.\" -*- tab-width: 4 -*- +.\" .\" Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. .\" -.\" @APPLE_LICENSE_HEADER_START@ +.\" Licensed under the Apache License, Version 2.0 (the "License"); +.\" you may not use this file except in compliance with the License. +.\" You may obtain a copy of the License at .\" -.\" This file contains Original Code and/or Modifications of Original Code -.\" as defined in and that are subject to the Apple Public Source License -.\" Version 2.0 (the 'License'). You may not use this file except in -.\" compliance with the License. Please obtain a copy of the License at -.\" http://www.opensource.apple.com/apsl/ and read it before using this -.\" file. +.\" http://www.apache.org/licenses/LICENSE-2.0 .\" -.\" The Original Code and all software distributed under the License are -.\" distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER -.\" EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, -.\" INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, -.\" FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. -.\" Please see the License for the specific language governing rights and +.\" Unless required by applicable law or agreed to in writing, software +.\" distributed under the License is distributed on an "AS IS" BASIS, +.\" WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +.\" See the License for the specific language governing permissions and .\" limitations under the License. -.\" -.\" @APPLE_LICENSE_HEADER_END@ .\" .\" $Log: dns-sd.1,v $ +.\" Revision 1.6 2006/08/14 23:24:56 cheshire +.\" Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 +.\" .\" Revision 1.5 2005/07/04 23:12:35 cheshire .\" The dns-sd command first appeared in Mac OS X 10.4 (Tiger) .\" diff --git a/mDNSShared/dns_sd.h b/mDNSShared/dns_sd.h index 3fd58ef..b7eb8a2 100755 --- a/mDNSShared/dns_sd.h +++ b/mDNSShared/dns_sd.h @@ -1,4 +1,5 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 2003-2004, Apple Computer, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -42,7 +43,7 @@ #endif /* stdint.h does not exist on FreeBSD 4.x; its types are defined in sys/types.h instead */ -#if defined(__FreeBSD_version) && (__FreeBSD_version < 500000) +#if defined(__FreeBSD__) && (__FreeBSD__ < 5) #include /* Likewise, on Sun, standard integer types are in sys/types.h */ @@ -145,10 +146,15 @@ enum * (queries from hosts more than one hop away; hosts not directly connected to the local link). */ - kDNSServiceFlagsForceMulticast = 0x400 + kDNSServiceFlagsForceMulticast = 0x400, /* Flag for signifying that a query or registration should be performed exclusively via multicast DNS, * even for a name in a domain (e.g. foo.apple.com.) that would normally imply unicast DNS. */ + + kDNSServiceFlagsReturnCNAME = 0x800 + /* Flag for returning CNAME records in the DNSServiceQueryRecord call. CNAME records are + * normally followed without indicating to the client that there was a CNAME record. + */ }; /* @@ -196,7 +202,7 @@ enum kDNSServiceType_KEY = 25, /* Security key. */ kDNSServiceType_PX = 26, /* X.400 mail mapping. */ kDNSServiceType_GPOS = 27, /* Geographical position (withdrawn). */ - kDNSServiceType_AAAA = 28, /* Ip6 Address. */ + kDNSServiceType_AAAA = 28, /* IPv6 Address. */ kDNSServiceType_LOC = 29, /* Location Information. */ kDNSServiceType_NXT = 30, /* Next domain (security). */ kDNSServiceType_EID = 31, /* Endpoint identifier. */ @@ -206,7 +212,7 @@ enum kDNSServiceType_NAPTR = 35, /* Naming Authority PoinTeR */ kDNSServiceType_KX = 36, /* Key Exchange */ kDNSServiceType_CERT = 37, /* Certification record */ - kDNSServiceType_A6 = 38, /* IPv6 address (deprecates AAAA) */ + kDNSServiceType_A6 = 38, /* IPv6 Address (deprecated) */ kDNSServiceType_DNAME = 39, /* Non-terminal DNAME (for IPv6) */ kDNSServiceType_SINK = 40, /* Kitchen sink (experimentatl) */ kDNSServiceType_OPT = 41, /* EDNS0 option (meta-RR) */ @@ -318,7 +324,7 @@ enum * * If the client passes 0 for interface index, that means "do the right thing", * which (at present) means, "if the name is in an mDNS local multicast domain - * (e.g. 'local.', '254.169.in-addr.arpa.', '0.8.E.F.ip6.arpa.') then multicast + * (e.g. 'local.', '254.169.in-addr.arpa.', '{8,9,A,B}.E.F.ip6.arpa.') then multicast * on all applicable interfaces, otherwise send via unicast to the appropriate * DNS server." Normally, most clients will use 0 for interface index to * automatically get the default sensible behaviour. @@ -623,6 +629,9 @@ typedef void (DNSSD_API *DNSServiceRegisterReply) * i.e. it creates a TXT record of length one containing a single empty string. * RFC 1035 doesn't allow a TXT record to contain *zero* strings, so a single empty * string is the smallest legal DNS TXT record. + * As with the other parameters, the DNSServiceRegister call copies the txtRecord + * data; e.g. if you allocated the storage for the txtRecord parameter with malloc() + * then you can safely free that memory right after the DNSServiceRegister call returns. * * callBack: The function to be called when the registration completes or asynchronously * fails. The client MAY pass NULL for the callback - The client will NOT be notified @@ -638,7 +647,6 @@ typedef void (DNSSD_API *DNSServiceRegisterReply) * errors are delivered to the callback), otherwise returns an error code indicating * the error that occurred (the callback is never invoked and the DNSServiceRef * is not initialized.) - * */ DNSServiceErrorType DNSSD_API DNSServiceRegister @@ -665,6 +673,12 @@ DNSServiceErrorType DNSSD_API DNSServiceRegister * The record can later be updated or deregistered by passing the RecordRef initialized * by this function to DNSServiceUpdateRecord() or DNSServiceRemoveRecord(). * + * Note that the DNSServiceAddRecord/UpdateRecord/RemoveRecord are *NOT* thread-safe + * with respect to a single DNSServiceRef. If you plan to have multiple threads + * in your program simultaneously add, update, or remove records from the same + * DNSServiceRef, then it's the caller's responsibility to use a mutext lock + * or take similar appropriate precautions to serialize those calls. + * * * Parameters; * @@ -914,9 +928,23 @@ DNSServiceErrorType DNSSD_API DNSServiceBrowse * * txtRecord: The service's primary txt record, in standard txt record format. * - * context: The context pointer that was passed to the callout. * + * NOTE: In earlier versions of this header file, the txtRecord parameter was declared "const char *" + * This is incorrect, since it contains length bytes which are values in the range 0 to 255, not -128 to +127. + * Depending on your compiler settings, this change may cause signed/unsigned mismatch warnings. + * These should be fixed by updating your own callback function definition to match the corrected + * function signature using "const unsigned char *txtRecord". Making this change may also fix inadvertent + * bugs in your callback function, where it could have incorrectly interpreted a length byte with value 250 + * as being -6 instead, with various bad consequences ranging from incorrect operation to software crashes. + * If you need to maintain portable code that will compile cleanly with both the old and new versions of + * this header file, you should update your callback function definition to use the correct unsigned value, + * and then in the place where you pass your callback function to DNSServiceResolve(), use a cast to eliminate + * the compiler warning, e.g.: + * DNSServiceResolve(sd, flags, index, name, regtype, domain, (DNSServiceResolveReply)MyCallback, context); + * This will ensure that your code compiles cleanly without warnings (and more importantly, works correctly) + * with both the old header and with the new corrected version. + * */ typedef void (DNSSD_API *DNSServiceResolveReply) @@ -929,7 +957,7 @@ typedef void (DNSSD_API *DNSServiceResolveReply) const char *hosttarget, uint16_t port, uint16_t txtLen, - const char *txtRecord, + const unsigned char *txtRecord, void *context ); @@ -1022,7 +1050,7 @@ DNSServiceErrorType DNSSD_API DNSServiceCreateConnection(DNSServiceRef *sdRef); * DNSServiceRegisterRecordReply() parameters: * * sdRef: The connected DNSServiceRef initialized by - * DNSServiceDiscoveryConnect(). + * DNSServiceCreateConnection(). * * RecordRef: The DNSRecordRef initialized by DNSServiceRegisterRecord(). If the above * DNSServiceRef is passed to DNSServiceRefDeallocate(), this DNSRecordRef is @@ -1237,7 +1265,7 @@ DNSServiceErrorType DNSSD_API DNSServiceQueryRecord * */ -void DNSSD_API DNSServiceReconfirmRecord +DNSServiceErrorType DNSSD_API DNSServiceReconfirmRecord ( DNSServiceFlags flags, uint32_t interfaceIndex, @@ -1443,7 +1471,6 @@ DNSServiceErrorType DNSSD_API TXTRecordSetValue * return value: Returns kDNSServiceErr_NoError on success. * Returns kDNSServiceErr_NoSuchKey if the "key" does not * exist in the TXTRecordRef. - * */ DNSServiceErrorType DNSSD_API TXTRecordRemoveValue @@ -1463,7 +1490,6 @@ DNSServiceErrorType DNSSD_API TXTRecordRemoveValue * which you can pass directly to DNSServiceRegister() or * to DNSServiceUpdateRecord(). * Returns 0 if the TXTRecordRef is empty. - * */ uint16_t DNSSD_API TXTRecordGetLength @@ -1481,7 +1507,6 @@ uint16_t DNSSD_API TXTRecordGetLength * return value: Returns a pointer to the raw bytes inside the TXTRecordRef * which you can pass directly to DNSServiceRegister() or * to DNSServiceUpdateRecord(). - * */ const void * DNSSD_API TXTRecordGetBytesPtr @@ -1536,7 +1561,6 @@ const void * DNSSD_API TXTRecordGetBytesPtr * * return value: Returns 1 if the TXT Record contains the specified key. * Otherwise, it returns 0. - * */ int DNSSD_API TXTRecordContainsKey diff --git a/mDNSShared/dnsextd.8 b/mDNSShared/dnsextd.8 index 12009f6..796ca84 100644 --- a/mDNSShared/dnsextd.8 +++ b/mDNSShared/dnsextd.8 @@ -1,25 +1,23 @@ +.\" -*- tab-width: 4 -*- +.\" .\" Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. .\" -.\" @APPLE_LICENSE_HEADER_START@ +.\" Licensed under the Apache License, Version 2.0 (the "License"); +.\" you may not use this file except in compliance with the License. +.\" You may obtain a copy of the License at .\" -.\" This file contains Original Code and/or Modifications of Original Code -.\" as defined in and that are subject to the Apple Public Source License -.\" Version 2.0 (the 'License'). You may not use this file except in -.\" compliance with the License. Please obtain a copy of the License at -.\" http://www.opensource.apple.com/apsl/ and read it before using this -.\" file. +.\" http://www.apache.org/licenses/LICENSE-2.0 .\" -.\" The Original Code and all software distributed under the License are -.\" distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER -.\" EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, -.\" INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, -.\" FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. -.\" Please see the License for the specific language governing rights and +.\" Unless required by applicable law or agreed to in writing, software +.\" distributed under the License is distributed on an "AS IS" BASIS, +.\" WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +.\" See the License for the specific language governing permissions and .\" limitations under the License. -.\" -.\" @APPLE_LICENSE_HEADER_END@ .\" .\" $Log: dnsextd.8,v $ +.\" Revision 1.2 2006/08/14 23:24:56 cheshire +.\" Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 +.\" .\" Revision 1.1 2004/08/15 18:49:18 cheshire .\" No man page for dnsextd .\" diff --git a/mDNSShared/dnsextd.c b/mDNSShared/dnsextd.c new file mode 100644 index 0000000..be795c5 --- /dev/null +++ b/mDNSShared/dnsextd.c @@ -0,0 +1,2118 @@ +/* -*- Mode: C; tab-width: 4 -*- + * + * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + + Change History (most recent first): + +$Log: dnsextd.c,v $ +Revision 1.33.2.2 2006/08/29 06:24:36 cheshire +Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 + +Revision 1.33.2.1 2005/08/05 21:14:00 ksekar + Long-lived queries not working on windows +Change constant names + +Revision 1.33 2005/03/11 19:09:02 ksekar +Fixed ZERO_LLQID macro + +Revision 1.32 2005/03/10 22:54:33 ksekar + dnsextd leaks memory/ports + +Revision 1.31 2005/02/24 02:37:57 ksekar + dnsextd memory management improvements + +Revision 1.30 2005/01/27 22:57:56 cheshire +Fix compile errors on gcc4 + +Revision 1.29 2004/12/22 00:13:50 ksekar + Change version, port, and polling interval for LLQ + +Revision 1.28 2004/12/17 00:30:00 ksekar + dnsextd memory leak + +Revision 1.27 2004/12/17 00:27:32 ksekar +Ignore SIGPIPE + +Revision 1.26 2004/12/17 00:21:33 ksekar +Fixes for new CacheRecord structure with indirect name pointer + +Revision 1.25 2004/12/16 20:13:02 cheshire + Cache memory management improvements + +Revision 1.24 2004/12/14 17:09:06 ksekar +fixed incorrect usage instructions + +Revision 1.23 2004/12/06 20:24:31 ksekar + dnsextd leaks sockets + +Revision 1.22 2004/12/03 20:20:29 ksekar + dnsextd: support delivery of large records via LLQ events + +Revision 1.21 2004/12/03 06:11:34 ksekar + clean up dnsextd arguments + +Revision 1.20 2004/12/01 04:27:28 cheshire + Darwin patches for Solaris and Suse +Don't use uint32_t, etc. -- they require stdint.h, which doesn't exist on FreeBSD 4.x, Solaris, etc. + +Revision 1.19 2004/12/01 01:16:29 cheshire +Solaris compatibility fixes + +Revision 1.18 2004/11/30 23:51:06 cheshire +Remove double semicolons + +Revision 1.17 2004/11/30 22:37:01 cheshire +Update copyright dates and add "Mode: C; tab-width: 4" headers + +Revision 1.16 2004/11/25 02:02:28 ksekar +Fixed verbose log message argument + +Revision 1.15 2004/11/19 02:35:02 ksekar + Wide Area Security: Add LLQ-ID to events + +Revision 1.14 2004/11/17 06:17:58 cheshire +Update comments to show correct SRV names: _dns-update._udp.. and _dns-llq._udp.. + +Revision 1.13 2004/11/13 02:22:36 ksekar + Refresh Acks from daemon malformatted + +Revision 1.12 2004/11/12 01:05:01 ksekar + dnsextd: daemon registers the SRV same record +twice at startup + +Revision 1.11 2004/11/12 01:03:31 ksekar + dnsextd: KnownAnswers (CacheRecords) leaked + +Revision 1.10 2004/11/12 00:35:28 ksekar + dnsextd: uninitialized pointer can cause crash + +Revision 1.9 2004/11/10 20:38:17 ksekar + dnsextd: allow a "fudge" in LLQ lease echo + +Revision 1.8 2004/11/01 17:48:14 cheshire +Changed SOA serial number back to signed. RFC 1035 may describe it as "unsigned", but +it's wrong. The SOA serial is a modular counter, as explained in "DNS & BIND", page +137. Since C doesn't have a modular type, we used signed, C's closest approximation. + +Revision 1.7 2004/10/30 00:06:58 ksekar + Support Long Lived Queries in DNS Extension daemon + +Revision 1.6 2004/09/17 01:08:54 cheshire +Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h + The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces + declared in that file are ONLY appropriate to single-address-space embedded applications. + For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used. + +Revision 1.5 2004/09/16 00:50:54 cheshire +Don't use MSG_WAITALL -- it returns "Invalid argument" on some Linux versions + +Revision 1.4 2004/09/14 23:27:48 cheshire +Fix compile errors + +Revision 1.3 2004/09/02 01:39:40 cheshire +For better readability, follow consistent convention that QR bit comes first, followed by OP bits + +Revision 1.2 2004/08/24 23:27:57 cheshire +Fixes for Linux compatibility: +Don't use strings.h +Don't assume SIGINFO +Don't try to set servaddr.sin_len on platforms that don't have sa_len + +Revision 1.1 2004/08/11 00:43:26 ksekar +: DNS Extension daemon for DNS Update Lease + +*/ + +#include "../mDNSCore/mDNSEmbeddedAPI.h" +#include "../mDNSCore/DNSCommon.h" +#include "../mDNSCore/mDNS.c" +//!!!KRS we #include mDNS.c for the various constants defined there - we should move these to DNSCommon.h + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Compatibility workaround +#ifndef AF_LOCAL +#define AF_LOCAL AF_UNIX +#endif + +// +// Constants +// + +#define LOOPBACK "127.0.0.1" +#define NS_PORT 53 +#define DAEMON_PORT 5352 // default, may be overridden via command line argument +#define LISTENQ 128 // tcp connection backlog +#define RECV_BUFLEN 9000 +#define LEASETABLE_INIT_NBUCKETS 256 // initial hashtable size (doubles as table fills) +#define LLQ_TABLESIZE 1024 // !!!KRS make this dynamically growable +#define EXPIRATION_INTERVAL 300 // check for expired records every 5 minutes +#define SRV_TTL 7200 // TTL For _dns-update SRV records + +// LLQ Lease bounds (seconds) +#define LLQ_MIN_LEASE (15 * 60) +#define LLQ_MAX_LEASE (120 * 60) +#define LLQ_LEASE_FUDGE 60 + +// LLQ SOA poll interval (microseconds) +#define LLQ_MONITOR_ERR_INTERVAL (60 * 1000000) +#define LLQ_MONITOR_INTERVAL 250000 +#ifdef SIGINFO +#define INFO_SIGNAL SIGINFO +#else +#define INFO_SIGNAL SIGUSR1 +#endif + +#define SAME_INADDR(x,y) (*((mDNSu32 *)&x) == *((mDNSu32 *)&y)) +#define ZERO_LLQID(x) (!memcmp(x, "\x0\x0\x0\x0\x0\x0\x0\x0", 8)) + +// +// Data Structures +// Structs/fields that must be locked for thread safety are explicitly commented +// + +typedef struct + { + struct sockaddr_in src; + size_t len; + DNSMessage msg; + // Note: extra storage for oversized (TCP) messages goes here + } PktMsg; + +// lease table entry +typedef struct RRTableElem + { + struct RRTableElem *next; + struct sockaddr_in cli; // client's source address + long expire; // expiration time, in seconds since epoch + domainname zone; // from zone field of update message + domainname name; // name of the record + CacheRecord rr; // last field in struct allows for allocation of oversized RRs + } RRTableElem; + +typedef enum + { + RequestReceived = 0, + ChallengeSent = 1, + Established = 2 + } LLQState; + +typedef struct AnswerListElem + { + struct AnswerListElem *next; + domainname name; + mDNSu16 type; + CacheRecord *KnownAnswers; // All valid answers delivered to client + CacheRecord *EventList; // New answers (adds/removes) to be sent to client + int refcount; + } AnswerListElem; + +// llq table entry +typedef struct LLQEntry + { + struct LLQEntry *next; + struct sockaddr_in cli; // clien'ts source address + domainname qname; + mDNSu16 qtype; + mDNSu8 id[8]; + LLQState state; + mDNSu32 lease; // original lease, in seconds + mDNSs32 expire; // expiration, absolute, in seconds since epoch + AnswerListElem *AnswerList; + } LLQEntry; + +// daemon-wide information +typedef struct + { + // server variables - read only after initialization (no locking) + struct in_addr saddr; // server address + domainname zone; // zone being updated + int tcpsd; // listening TCP socket + int udpsd; // listening UDP socket + + // daemon variables - read only after initialization (no locking) + uDNS_AuthInfo *AuthInfo; // linked list of keys for signing deletion updates + mDNSIPPort port; // listening port + + // lease table variables (locked via mutex after initialization) + RRTableElem **table; // hashtable for records with leases + pthread_mutex_t tablelock; // mutex for lease table + mDNSs32 nbuckets; // buckets allocated + mDNSs32 nelems; // elements in table + + // LLQ table variables + LLQEntry *LLQTable[LLQ_TABLESIZE]; // !!!KRS change this and RRTable to use a common data structure + AnswerListElem *AnswerTable[LLQ_TABLESIZE]; + int LLQEventListenSock; // Unix domain socket pair - polling thread writes to ServPollSock, which wakes + int LLQServPollSock; // the main thread listening on EventListenSock, indicating that the zone has changed + } DaemonInfo; + +// args passed to UDP request handler thread as void* +typedef struct + { + PktMsg pkt; + struct sockaddr_in cliaddr; + DaemonInfo *d; + } UDPRequestArgs; + +// args passed to TCP request handler thread as void* +typedef struct + { + int sd; // socket connected to client + struct sockaddr_in cliaddr; + DaemonInfo *d; + } TCPRequestArgs; + +// +// Global Variables +// + +// booleans to determine runtime output +// read-only after initialization (no mutex protection) +static mDNSBool foreground = 0; +static mDNSBool verbose = 0; + +// globals set via signal handler (accessed exclusively by main select loop and signal handler) +static mDNSBool terminate = 0; +static mDNSBool dumptable = 0; + +// +// Logging Routines +// Log messages are delivered to syslog unless -f option specified +// + +// common message logging subroutine +mDNSlocal void PrintLog(const char *buffer) + { + if (foreground) + { + fprintf(stderr,"%s\n", buffer); + fflush(stderr); + } + else + { + openlog("dnsextd", LOG_CONS | LOG_PERROR, LOG_DAEMON); + syslog(LOG_ERR, "%s", buffer); + closelog(); + } + } + +// Verbose Logging (conditional on -v option) +mDNSlocal void VLog(const char *format, ...) + { + char buffer[512]; + va_list ptr; + + if (!verbose) return; + va_start(ptr,format); + buffer[mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr)] = 0; + va_end(ptr); + PrintLog(buffer); + } + +// Unconditional Logging +mDNSlocal void Log(const char *format, ...) + { + char buffer[512]; + va_list ptr; + + va_start(ptr,format); + buffer[mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr)] = 0; + va_end(ptr); + PrintLog(buffer); + } + +// Error Logging +// prints message "dnsextd : - " +// must be compiled w/ -D_REENTRANT for thread-safe errno usage +mDNSlocal void LogErr(const char *fn, const char *operation) + { + char buf[512]; + snprintf(buf, sizeof(buf), "%s: %s - %s", fn, operation, strerror(errno)); + PrintLog(buf); + } + +// +// Networking Utility Routines +// + +// Convert DNS Message Header from Network to Host byte order +mDNSlocal void HdrNToH(PktMsg *pkt) + { + // Read the integer parts which are in IETF byte-order (MSB first, LSB second) + mDNSu8 *ptr = (mDNSu8 *)&pkt->msg.h.numQuestions; + pkt->msg.h.numQuestions = (mDNSu16)((mDNSu16)ptr[0] << 8 | ptr[1]); + pkt->msg.h.numAnswers = (mDNSu16)((mDNSu16)ptr[2] << 8 | ptr[3]); + pkt->msg.h.numAuthorities = (mDNSu16)((mDNSu16)ptr[4] << 8 | ptr[5]); + pkt->msg.h.numAdditionals = (mDNSu16)((mDNSu16)ptr[6] << 8 | ptr[7]); + } + +// Convert DNS Message Header from Host to Network byte order +mDNSlocal void HdrHToN(PktMsg *pkt) + { + mDNSu16 numQuestions = pkt->msg.h.numQuestions; + mDNSu16 numAnswers = pkt->msg.h.numAnswers; + mDNSu16 numAuthorities = pkt->msg.h.numAuthorities; + mDNSu16 numAdditionals = pkt->msg.h.numAdditionals; + mDNSu8 *ptr = (mDNSu8 *)&pkt->msg.h.numQuestions; + + // Put all the integer values in IETF byte-order (MSB first, LSB second) + *ptr++ = (mDNSu8)(numQuestions >> 8); + *ptr++ = (mDNSu8)(numQuestions & 0xFF); + *ptr++ = (mDNSu8)(numAnswers >> 8); + *ptr++ = (mDNSu8)(numAnswers & 0xFF); + *ptr++ = (mDNSu8)(numAuthorities >> 8); + *ptr++ = (mDNSu8)(numAuthorities & 0xFF); + *ptr++ = (mDNSu8)(numAdditionals >> 8); + *ptr++ = (mDNSu8)(numAdditionals & 0xFF); + } + +// create a socket connected to nameserver +// caller terminates connection via close() +mDNSlocal int ConnectToServer(DaemonInfo *d) + { + struct sockaddr_in servaddr; + int sd; + + bzero(&servaddr, sizeof(servaddr)); + if (d->saddr.s_addr) servaddr.sin_addr = d->saddr; + else inet_pton(AF_INET, LOOPBACK, &d->saddr); // use loopback if server not explicitly specified + servaddr.sin_port = htons(NS_PORT); + servaddr.sin_family = AF_INET; +#ifndef NOT_HAVE_SA_LEN + servaddr.sin_len = sizeof(servaddr); +#endif + sd = socket(AF_INET, SOCK_STREAM, 0); + if (sd < 0) { LogErr("ConnectToServer", "socket"); return -1; } + if (connect(sd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) { LogErr("ConnectToServer", "connect"); return -1; } + return sd; + } + +// send an entire block of data over a connected socket, blocking if buffers are full +mDNSlocal int MySend(int sd, const void *msg, int len) + { + int n, nsent = 0; + + while (nsent < len) + { + n = send(sd, (char *)msg + nsent, len - nsent, 0); + if (n < 0) { LogErr("MySend", "send"); return -1; } + nsent += n; + } + return 0; + } + +// Transmit a DNS message, prefixed by its length, over TCP, blocking if necessary +mDNSlocal int SendTCPMsg(int sd, PktMsg *pkt) + { + // send the lenth, in network byte order + mDNSu16 len = htons((mDNSu16)pkt->len); + if (MySend(sd, &len, sizeof(len)) < 0) return -1; + + // send the message + return MySend(sd, &pkt->msg, pkt->len); + } + +// Receive len bytes, waiting until we have all of them. +// Returns number of bytes read (which should always be the number asked for). +static int my_recv(const int sd, void *const buf, const int len) + { + // Don't use "MSG_WAITALL"; it returns "Invalid argument" on some Linux versions; + // use an explicit while() loop instead. + // Also, don't try to do '+=' arithmetic on the original "void *" pointer -- + // arithmetic on "void *" pointers is compiler-dependent. + int remaining = len; + char *ptr = (char *)buf; + while (remaining) + { + ssize_t num_read = recv(sd, ptr, remaining, 0); + if ((num_read == 0) || (num_read < 0) || (num_read > remaining)) return -1; + ptr += num_read; + remaining -= num_read; + } + return(len); + } + +// Return a DNS Message read off of a TCP socket, or NULL on failure +// If storage is non-null, result is placed in that buffer. Otherwise, +// returned value is allocated with Malloc, and contains sufficient extra +// storage for a Lease OPT RR + +mDNSlocal PktMsg *ReadTCPMsg(int sd, PktMsg *storage) + { + int nread, allocsize; + mDNSu16 msglen = 0; + PktMsg *pkt = NULL; + unsigned int srclen; + + nread = my_recv(sd, &msglen, sizeof(msglen)); + if (nread < 0) { LogErr("TCPRequestForkFn", "recv"); goto error; } + msglen = ntohs(msglen); + if (nread != sizeof(msglen)) { Log("Could not read length field of message"); goto error; } + + if (storage) + { + if (msglen > sizeof(storage->msg)) { Log("ReadTCPMsg: provided buffer too small."); goto error; } + pkt = storage; + } + else + { + // buffer extra space to add an OPT RR + if (msglen > sizeof(DNSMessage)) allocsize = sizeof(PktMsg) - sizeof(DNSMessage) + msglen; + else allocsize = sizeof(PktMsg); + pkt = malloc(allocsize); + if (!pkt) { LogErr("ReadTCPMsg", "malloc"); goto error; } + bzero(pkt, sizeof(*pkt)); + } + + pkt->len = msglen; + srclen = sizeof(pkt->src); + if (getpeername(sd, (struct sockaddr *)&pkt->src, &srclen) || + srclen != sizeof(pkt->src)) { LogErr("ReadTCPMsg", "getpeername"); bzero(&pkt->src, sizeof(pkt->src)); } + nread = my_recv(sd, &pkt->msg, msglen); + if (nread < 0) { LogErr("TCPRequestForkFn", "recv"); goto error; } + if (nread != msglen) { Log("Could not read entire message"); goto error; } + if (pkt->len < sizeof(DNSMessageHeader)) + { Log("ReadTCPMsg: Message too short (%d bytes)", pkt->len); goto error; } + HdrNToH(pkt); + return pkt; + //!!!KRS convert to HBO here? + error: + if (pkt && pkt != storage) free(pkt); + return NULL; + } + +// +// Dynamic Update Utility Routines +// + +// Get the lease life of records in a dynamic update +// returns -1 on error or if no lease present +mDNSlocal mDNSs32 GetPktLease(PktMsg *pkt) + { + mDNSs32 lease = -1; + const mDNSu8 *ptr = NULL, *end = (mDNSu8 *)&pkt->msg + pkt->len; + LargeCacheRecord lcr; + int i; + + HdrNToH(pkt); + ptr = LocateAdditionals(&pkt->msg, end); + if (ptr) + for (i = 0; i < pkt->msg.h.numAdditionals; i++) + { + ptr = GetLargeResourceRecord(NULL, &pkt->msg, ptr, end, 0, kDNSRecordTypePacketAdd, &lcr); + if (!ptr) { Log("Unable to read additional record"); break; } + if (lcr.r.resrec.rrtype == kDNSType_OPT) + { + if (lcr.r.resrec.rdlength < LEASE_OPT_RDLEN) continue; + if (lcr.r.resrec.rdata->u.opt.opt != kDNSOpt_Lease) continue; + lease = (mDNSs32)lcr.r.resrec.rdata->u.opt.OptData.lease; + break; + } + } + + HdrHToN(pkt); + return lease; + } + +// check if a request and server response complete a successful dynamic update +mDNSlocal mDNSBool SuccessfulUpdateTransaction(PktMsg *request, PktMsg *reply) + { + char buf[32]; + char *vlogmsg = NULL; + + // check messages + if (!request || !reply) { vlogmsg = "NULL message"; goto failure; } + if (request->len < sizeof(DNSMessageHeader) || reply->len < sizeof(DNSMessageHeader)) { vlogmsg = "Malformatted message"; goto failure; } + + // check request operation + if ((request->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask) != (request->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask)) + { vlogmsg = "Request opcode not an update"; goto failure; } + + // check result + if ((reply->msg.h.flags.b[1] & kDNSFlag1_RC)) { vlogmsg = "Reply contains non-zero rcode"; goto failure; } + if ((reply->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask) != (kDNSFlag0_OP_Update | kDNSFlag0_QR_Response)) + { vlogmsg = "Reply opcode not an update response"; goto failure; } + + VLog("Successful update from %s", inet_ntop(AF_INET, &request->src.sin_addr, buf, 32)); + return mDNStrue; + + failure: + VLog("Request %s: %s", inet_ntop(AF_INET, &request->src.sin_addr, buf, 32), vlogmsg); + return mDNSfalse; + } + +// Allocate an appropriately sized CacheRecord and copy data from original. +// Name pointer in CacheRecord object is set to point to the name specified +// +mDNSlocal CacheRecord *CopyCacheRecord(const CacheRecord *orig, domainname *name) + { + CacheRecord *cr; + size_t size = sizeof(*cr); + if (orig->resrec.rdlength > InlineCacheRDSize) size += orig->resrec.rdlength - InlineCacheRDSize; + cr = malloc(size); + if (!cr) { LogErr("CopyCacheRecord", "malloc"); return NULL; } + memcpy(cr, orig, size); + cr->resrec.rdata = (RData*)&cr->rdatastorage; + cr->resrec.name = name; + + return cr; + } + + +// +// Lease Hashtable Utility Routines +// + +// double hash table size +// caller must lock table prior to invocation +mDNSlocal void RehashTable(DaemonInfo *d) + { + RRTableElem *ptr, *tmp, **new; + int i, bucket, newnbuckets = d->nbuckets * 2; + + VLog("Rehashing lease table (new size %d buckets)", newnbuckets); + new = malloc(sizeof(RRTableElem *) * newnbuckets); + if (!new) { LogErr("RehashTable", "malloc"); return; } + bzero(new, newnbuckets * sizeof(RRTableElem *)); + + for (i = 0; i < d->nbuckets; i++) + { + ptr = d->table[i]; + while (ptr) + { + bucket = ptr->rr.resrec.namehash % newnbuckets; + tmp = ptr; + ptr = ptr->next; + tmp->next = new[bucket]; + new[bucket] = tmp; + } + } + d->nbuckets = newnbuckets; + free(d->table); + d->table = new; + } + +// print entire contents of hashtable, invoked via SIGINFO +mDNSlocal void PrintLeaseTable(DaemonInfo *d) + { + int i; + RRTableElem *ptr; + char rrbuf[80], addrbuf[16]; + struct timeval now; + int hr, min, sec; + + if (gettimeofday(&now, NULL)) { LogErr("PrintTable", "gettimeofday"); return; } + if (pthread_mutex_lock(&d->tablelock)) { LogErr("PrintTable", "pthread_mutex_lock"); return; } + + Log("Dumping Lease Table Contents (table contains %d resource records)", d->nelems); + for (i = 0; i < d->nbuckets; i++) + { + for (ptr = d->table[i]; ptr; ptr = ptr->next) + { + hr = ((ptr->expire - now.tv_sec) / 60) / 60; + min = ((ptr->expire - now.tv_sec) / 60) % 60; + sec = (ptr->expire - now.tv_sec) % 60; + Log("Update from %s, Expires in %d:%d:%d\n\t%s", inet_ntop(AF_INET, &ptr->cli.sin_addr, addrbuf, 16), hr, min, sec, + GetRRDisplayString_rdb(&ptr->rr.resrec, &ptr->rr.resrec.rdata->u, rrbuf)); + } + } + pthread_mutex_unlock(&d->tablelock); + } + +// +// Startup SRV Registration Routines +// Register _dns-update._udp/_tcp. SRV records indicating the port on which +// the daemon accepts requests +// + +// delete all RRS of a given name/type +mDNSlocal mDNSu8 *putRRSetDeletion(DNSMessage *msg, mDNSu8 *ptr, mDNSu8 *limit, ResourceRecord *rr) + { + ptr = putDomainNameAsLabels(msg, ptr, limit, rr->name); + if (!ptr || ptr + 10 >= limit) return NULL; // out of space + ptr[0] = (mDNSu8)(rr->rrtype >> 8); + ptr[1] = (mDNSu8)(rr->rrtype & 0xFF); + ptr[2] = (mDNSu8)((mDNSu16)kDNSQClass_ANY >> 8); + ptr[3] = (mDNSu8)((mDNSu16)kDNSQClass_ANY & 0xFF); + bzero(ptr+4, sizeof(rr->rroriginalttl) + sizeof(rr->rdlength)); // zero ttl/rdata + msg->h.mDNS_numUpdates++; + return ptr + 10; + } + +mDNSlocal mDNSu8 *PutUpdateSRV(DaemonInfo *d, PktMsg *pkt, mDNSu8 *ptr, char *regtype, mDNSBool registration) + { + AuthRecord rr; + char hostname[1024], buf[80]; + mDNSu8 *end = (mDNSu8 *)&pkt->msg + sizeof(DNSMessage); + + mDNS_SetupResourceRecord(&rr, NULL, 0, kDNSType_SRV, SRV_TTL, kDNSRecordTypeUnique, NULL, NULL); + rr.resrec.rrclass = kDNSClass_IN; + rr.resrec.rdata->u.srv.priority = 0; + rr.resrec.rdata->u.srv.weight = 0; + rr.resrec.rdata->u.srv.port.NotAnInteger = d->port.NotAnInteger; + if (!gethostname(hostname, 1024) < 0 || MakeDomainNameFromDNSNameString(&rr.resrec.rdata->u.srv.target, hostname)) + rr.resrec.rdata->u.srv.target.c[0] = '\0'; + + MakeDomainNameFromDNSNameString(rr.resrec.name, regtype); + AppendDomainName(rr.resrec.name, &d->zone); + VLog("%s %s", registration ? "Registering SRV record" : "Deleting existing RRSet", + GetRRDisplayString_rdb(&rr.resrec, &rr.resrec.rdata->u, buf)); + if (registration) ptr = PutResourceRecord(&pkt->msg, ptr, &pkt->msg.h.mDNS_numUpdates, &rr.resrec); + else ptr = putRRSetDeletion(&pkt->msg, ptr, end, &rr.resrec); + return ptr; + } + + +// perform dynamic update. +// specify deletion by passing false for the register parameter, otherwise register the records. +mDNSlocal int UpdateSRV(DaemonInfo *d, mDNSBool registration) + { + int sd = -1; + mDNSOpaque16 id; + PktMsg pkt; + mDNSu8 *ptr = pkt.msg.data; + mDNSu8 *end = (mDNSu8 *)&pkt.msg + sizeof(DNSMessage); + mDNSu16 nAdditHBO; // num additionas, in host byte order, required by message digest routine + PktMsg *reply = NULL; + + int result = -1; + + // Initialize message + id.NotAnInteger = 0; + InitializeDNSMessage(&pkt.msg.h, id, UpdateReqFlags); + pkt.src.sin_addr.s_addr = htonl(INADDR_ANY); // address field set solely for verbose logging in subroutines + pkt.src.sin_family = AF_INET; + + // format message body + ptr = putZone(&pkt.msg, ptr, end, &d->zone, mDNSOpaque16fromIntVal(kDNSClass_IN)); + if (!ptr) goto end; + + ptr = PutUpdateSRV(d, &pkt, ptr, "_dns-update._udp.", registration); if (!ptr) goto end; + ptr = PutUpdateSRV(d, &pkt, ptr, "_dns-update._tcp.", registration); if (!ptr) goto end; + ptr = PutUpdateSRV(d, &pkt, ptr, "_dns-llq._udp.", registration); if (!ptr) goto end; + + nAdditHBO = pkt.msg.h.numAdditionals; + HdrHToN(&pkt); + if (d->AuthInfo) + { + ptr = DNSDigest_SignMessage(&pkt.msg, &ptr, &nAdditHBO, d->AuthInfo); + if (!ptr) goto end; + } + pkt.len = ptr - (mDNSu8 *)&pkt.msg; + + // send message, receive reply + sd = ConnectToServer(d); + if (sd < 0) { Log("UpdateSRV: ConnectToServer failed"); goto end; } + if (SendTCPMsg(sd, &pkt)) { Log("UpdateSRV: SendTCPMsg failed"); } + reply = ReadTCPMsg(sd, NULL); + if (!SuccessfulUpdateTransaction(&pkt, reply)) + Log("SRV record registration failed with rcode %d", reply->msg.h.flags.b[1] & kDNSFlag1_RC); + else result = 0; + + end: + if (!ptr) { Log("UpdateSRV: Error constructing lease expiration update"); } + if (sd >= 0) close(sd); + if (reply) free(reply); + return result; + } + +// wrapper routines/macros +#define ClearUpdateSRV(d) UpdateSRV(d, 0) + +// clear any existing records prior to registration +mDNSlocal int SetUpdateSRV(DaemonInfo *d) + { + int err; + + err = ClearUpdateSRV(d); // clear any existing record + if (!err) err = UpdateSRV(d, 1); + return err; + } + +// +// Argument Parsing and Configuration +// + +// read authentication information for a zone from command line argument +// global optind corresponds to keyname argument on entry +mDNSlocal int ReadAuthKey(int argc, char *argv[], DaemonInfo *d) + { + uDNS_AuthInfo *auth = NULL; + unsigned char keybuf[512]; + mDNSs32 keylen; + + auth = malloc(sizeof(*auth)); + if (!auth) { perror("ReadAuthKey, malloc"); goto error; } + auth->next = NULL; + if (argc < optind + 1) return -1; // keyname + secret + if (!MakeDomainNameFromDNSNameString(&auth->keyname, optarg)) + { fprintf(stderr, "Bad key name %s", optarg); goto error; } + keylen = DNSDigest_Base64ToBin(argv[optind++], keybuf, 512); + if (keylen < 0) + { fprintf(stderr, "Bad shared secret %s (must be base-64 encoded string)", argv[optind-1]); goto error; } + DNSDigest_ConstructHMACKey(auth, keybuf, (mDNSu32)keylen); + d->AuthInfo = auth; + return 0; + + error: + if (auth) free(auth); + return -1; + } + +mDNSlocal int SetPort(DaemonInfo *d, char *PortAsString) + { + long l; + + l = strtol(PortAsString, NULL, 10); // convert string to long + if ((!l && errno == EINVAL) || l > 65535) return -1; // error check conversion + d->port.NotAnInteger = htons((mDNSu16)l); // set to network byte order + return 0; + } + +mDNSlocal void PrintUsage(void) + { + fprintf(stderr, "Usage: dnsextd -z [-vf] [ -s server ] [-k keyname secret] ...\n" + "Use \"dnsextd -h\" for help\n"); + } + +mDNSlocal void PrintHelp(void) + { + fprintf(stderr, "\n\n"); + PrintUsage(); + + fprintf(stderr, + "dnsextd is a daemon that implements DNS extensions supporting Dynamic DNS Update Leases\n" + "and Long Lived Queries, used in Wide-Area DNS Service Discovery, on behalf of name servers\n" + "that do not natively support these extensions. (See dns-sd.org for more info on DNS Service\n" + "Discovery, Update Leases, and Long Lived Queries.)\n\n" + + "dnsextd requires one argument,the zone, which is the domain for which Update Leases\n" + "and Long Lived Queries are to be administered. dnsextd communicates directly with the\n" + "primary master server for this zone.\n\n" + + "The options are as follows:\n\n" + + "-f Run daemon in foreground.\n\n" + + "-h Print help.\n\n" + + "-k Specify TSIG authentication key for dynamic updates from daemon to name server.\n" + " -k option is followed by the name of the key, and the shared secret as a base-64\n" + " encoded string. This key/secret are used by the daemon to delete resource records\n" + " from the server when leases expire. Clients are responsible for signing their\n" + " update requests.\n\n" + + "-s Specify address (IPv4 address in dotted-decimal notation) of the Primary Master\n" + " name server. Defaults to loopback (127.0.0.1), i.e. daemon and name server\n" + " running on the same machine.\n\n" + + "-v Verbose output.\n\n" + ); + } + +// Note: ProcessArgs called before process is daemonized, and therefore must open no descriptors +// returns 0 (success) if program is to continue execution +// output control arguments (-f, -v) do not affect this routine +mDNSlocal int ProcessArgs(int argc, char *argv[], DaemonInfo *d) + { + int opt; + + if (argc < 2) goto arg_error; + + d->port.NotAnInteger = htons(DAEMON_PORT); // default, may be overriden by command option + while ((opt = getopt(argc, argv, "z:p:hfvs:k:")) != -1) + { + switch(opt) + { + case 'p': if (SetPort(d, optarg) < 0) goto arg_error; + break; + + case 'h': PrintHelp(); return -1; + case 'f': foreground = 1; break; + case 'v': verbose = 1; break; + case 's': if (!inet_pton(AF_INET, optarg, &d->saddr)) goto arg_error; + break; + case 'k': if (ReadAuthKey(argc, argv, d) < 0) goto arg_error; + break; + case 'z': if (!MakeDomainNameFromDNSNameString(&d->zone, optarg)) + { + fprintf(stderr, "Bad zone %s", optarg); + goto arg_error; + } + break; + default: goto arg_error; + } + } + + if (!d->zone.c[0]) goto arg_error; // zone is the only required argument + if (d->AuthInfo) AssignDomainName(&d->AuthInfo->zone, &d->zone); // if we have a shared secret, use it for the entire zone + return 0; + + arg_error: + PrintUsage(); + return -1; + } + + +// +// Initialization Routines +// + +// Allocate memory, initialize locks and bookkeeping variables +mDNSlocal int InitLeaseTable(DaemonInfo *d) + { + if (pthread_mutex_init(&d->tablelock, NULL)) { LogErr("InitLeaseTable", "pthread_mutex_init"); return -1; } + d->nbuckets = LEASETABLE_INIT_NBUCKETS; + d->nelems = 0; + d->table = malloc(sizeof(RRTableElem *) * LEASETABLE_INIT_NBUCKETS); + if (!d->table) { LogErr("InitLeaseTable", "malloc"); return -1; } + bzero(d->table, sizeof(RRTableElem *) * LEASETABLE_INIT_NBUCKETS); + return 0; + } +mDNSlocal int SetupSockets(DaemonInfo *daemon) + { + struct sockaddr_in daddr; + int sockpair[2]; + + // set up sockets on which we receive requests + bzero(&daddr, sizeof(daddr)); + daddr.sin_family = AF_INET; + daddr.sin_addr.s_addr = htonl(INADDR_ANY); + + if (daemon->port.NotAnInteger) daddr.sin_port = daemon->port.NotAnInteger; + else daddr.sin_port = htons(DAEMON_PORT); + + daemon->tcpsd = socket(AF_INET, SOCK_STREAM, 0); + if (!daemon->tcpsd) { LogErr("SetupSockets", "socket"); return -1; } + if (bind(daemon->tcpsd, (struct sockaddr *)&daddr, sizeof(daddr)) < 0) { LogErr("SetupSockets", "bind"); return -1; } + if (listen(daemon->tcpsd, LISTENQ) < 0) { LogErr("SetupSockets", "listen"); return -1; } + + daemon->udpsd = socket(AF_INET, SOCK_DGRAM, 0); + if (!daemon->udpsd) { LogErr("SetupSockets", "socket"); return -1; } + if (bind(daemon->udpsd, (struct sockaddr *)&daddr, sizeof(daddr)) < 0) { LogErr("SetupSockets", "bind"); return -1; } + + // set up Unix domain socket pair for LLQ polling thread to signal main thread that a change to the zone occurred + if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sockpair) < 0) { LogErr("SetupSockets", "socketpair"); return -1; } + daemon->LLQEventListenSock = sockpair[0]; + daemon->LLQServPollSock = sockpair[1]; + return 0; + } + +// +// periodic table updates +// + +// Delete a resource record from the nameserver via a dynamic update +mDNSlocal void DeleteRecord(DaemonInfo *d, CacheRecord *rr, domainname *zone) + { + int sd = -1; + mDNSOpaque16 id; + PktMsg pkt; + mDNSu8 *ptr = pkt.msg.data; + mDNSu8 *end = (mDNSu8 *)&pkt.msg + sizeof(DNSMessage); + mDNSu16 nAdditHBO; // num additionas, in host byte order, required by message digest routine + char buf[80]; + PktMsg *reply = NULL; + + VLog("Expiring record %s", GetRRDisplayString_rdb(&rr->resrec, &rr->resrec.rdata->u, buf)); + sd = ConnectToServer(d); + if (sd < 0) { Log("DeleteRecord: ConnectToServer failed"); goto end; } + + id.NotAnInteger = 0; + InitializeDNSMessage(&pkt.msg.h, id, UpdateReqFlags); + + ptr = putZone(&pkt.msg, ptr, end, zone, mDNSOpaque16fromIntVal(rr->resrec.rrclass)); + if (!ptr) goto end; + ptr = putDeletionRecord(&pkt.msg, ptr, &rr->resrec); + if (!ptr) goto end; + + nAdditHBO = pkt.msg.h.numAdditionals; + HdrHToN(&pkt); + + if (d->AuthInfo) + { + ptr = DNSDigest_SignMessage(&pkt.msg, &ptr, &nAdditHBO, d->AuthInfo); + if (!ptr) goto end; + } + + pkt.len = ptr - (mDNSu8 *)&pkt.msg; + pkt.src.sin_addr.s_addr = htonl(INADDR_ANY); // address field set solely for verbose logging in subroutines + pkt.src.sin_family = AF_INET; + if (SendTCPMsg(sd, &pkt)) { Log("DeleteRecord: SendTCPMsg failed"); } + reply = ReadTCPMsg(sd, NULL); + if (!SuccessfulUpdateTransaction(&pkt, reply)) + Log("Expiration update failed with rcode %d", reply->msg.h.flags.b[1] & kDNSFlag1_RC); + + end: + if (!ptr) { Log("DeleteRecord: Error constructing lease expiration update"); } + if (sd >= 0) close(sd); + if (reply) free(reply); + } + +// iterate over table, deleting expired records +mDNSlocal void DeleteExpiredRecords(DaemonInfo *d) + { + int i; + RRTableElem *ptr, *prev, *fptr; + struct timeval now; + + if (gettimeofday(&now, NULL)) { LogErr("DeleteExpiredRecords ", "gettimeofday"); return; } + if (pthread_mutex_lock(&d->tablelock)) { LogErr("DeleteExpiredRecords", "pthread_mutex_lock"); return; } + for (i = 0; i < d->nbuckets; i++) + { + ptr = d->table[i]; + prev = NULL; + while (ptr) + { + if (ptr->expire - now.tv_sec < 0) + { + // delete record from server + DeleteRecord(d, &ptr->rr, &ptr->zone); + if (prev) prev->next = ptr->next; + else d->table[i] = ptr->next; + fptr = ptr; + ptr = ptr->next; + free(fptr); + d->nelems--; + } + else + { + prev = ptr; + ptr = ptr->next; + } + } + } + pthread_mutex_unlock(&d->tablelock); + } + +// +// main update request handling +// + +// Add, delete, or refresh records in table based on contents of a successfully completed dynamic update +mDNSlocal void UpdateLeaseTable(PktMsg *pkt, DaemonInfo *d, mDNSs32 lease) + { + RRTableElem **rptr, *tmp; + int i, allocsize, bucket; + LargeCacheRecord lcr; + ResourceRecord *rr = &lcr.r.resrec; + const mDNSu8 *ptr, *end; + struct timeval time; + DNSQuestion zone; + char buf[80]; + + if (pthread_mutex_lock(&d->tablelock)) { LogErr("UpdateLeaseTable", "pthread_mutex_lock"); return; } + HdrNToH(pkt); + ptr = pkt->msg.data; + end = (mDNSu8 *)&pkt->msg + pkt->len; + ptr = getQuestion(&pkt->msg, ptr, end, 0, &zone); + if (!ptr) { Log("UpdateLeaseTable: cannot read zone"); goto cleanup; } + ptr = LocateAuthorities(&pkt->msg, end); + if (!ptr) { Log("UpdateLeaseTable: Format error"); goto cleanup; } + + for (i = 0; i < pkt->msg.h.mDNS_numUpdates; i++) + { + mDNSBool DeleteAllRRSets = mDNSfalse, DeleteOneRRSet = mDNSfalse, DeleteOneRR = mDNSfalse; + + ptr = GetLargeResourceRecord(NULL, &pkt->msg, ptr, end, 0, kDNSRecordTypePacketAns, &lcr); + if (!ptr) { Log("UpdateLeaseTable: GetLargeResourceRecord returned NULL"); goto cleanup; } + bucket = rr->namehash % d->nbuckets; + rptr = &d->table[bucket]; + + // handle deletions + if (rr->rrtype == kDNSQType_ANY && !rr->rroriginalttl && rr->rrclass == kDNSQClass_ANY && !rr->rdlength) + DeleteAllRRSets = mDNStrue; // delete all rrsets for a name + else if (!rr->rroriginalttl && rr->rrclass == kDNSQClass_ANY && !rr->rdlength) + DeleteOneRRSet = mDNStrue; + else if (!rr->rroriginalttl && rr->rrclass == kDNSClass_NONE) + DeleteOneRR = mDNStrue; + + if (DeleteAllRRSets || DeleteOneRRSet || DeleteOneRR) + { + while (*rptr) + { + if (SameDomainName((*rptr)->rr.resrec.name, rr->name) && + (DeleteAllRRSets || + (DeleteOneRRSet && (*rptr)->rr.resrec.rrtype == rr->rrtype) || + (DeleteOneRR && SameResourceRecord(&(*rptr)->rr.resrec, rr)))) + { + tmp = *rptr; + VLog("Received deletion update for %s", GetRRDisplayString_rdb(&tmp->rr.resrec, &tmp->rr.resrec.rdata->u, buf)); + *rptr = (*rptr)->next; + free(tmp); + d->nelems--; + } + else rptr = &(*rptr)->next; + } + } + else if (lease > 0) + { + // see if add or refresh + while (*rptr && !SameResourceRecord(&(*rptr)->rr.resrec, rr)) rptr = &(*rptr)->next; + if (*rptr) + { + // refresh + if (gettimeofday(&time, NULL)) { LogErr("UpdateLeaseTable", "gettimeofday"); goto cleanup; } + (*rptr)->expire = time.tv_sec + (unsigned)lease; + VLog("Refreshing lease for %s", GetRRDisplayString_rdb(&lcr.r.resrec, &lcr.r.resrec.rdata->u, buf)); + } + else + { + // New record - add to table + if (d->nelems > d->nbuckets) + { + RehashTable(d); + bucket = rr->namehash % d->nbuckets; + rptr = &d->table[bucket]; + } + if (gettimeofday(&time, NULL)) { LogErr("UpdateLeaseTable", "gettimeofday"); goto cleanup; } + allocsize = sizeof(RRTableElem); + if (rr->rdlength > InlineCacheRDSize) allocsize += (rr->rdlength - InlineCacheRDSize); + tmp = malloc(allocsize); + if (!tmp) { LogErr("UpdateLeaseTable", "malloc"); goto cleanup; } + memcpy(&tmp->rr, &lcr.r, sizeof(CacheRecord) + rr->rdlength - InlineCacheRDSize); + tmp->rr.resrec.rdata = (RData *)&tmp->rr.rdatastorage; + AssignDomainName(&tmp->name, rr->name); + tmp->rr.resrec.name = &tmp->name; + tmp->expire = time.tv_sec + (unsigned)lease; + tmp->cli.sin_addr = pkt->src.sin_addr; + AssignDomainName(&tmp->zone, &zone.qname); + tmp->next = d->table[bucket]; + d->table[bucket] = tmp; + d->nelems++; + VLog("Adding update for %s to lease table", GetRRDisplayString_rdb(&lcr.r.resrec, &lcr.r.resrec.rdata->u, buf)); + } + } + } + + cleanup: + pthread_mutex_unlock(&d->tablelock); + HdrHToN(pkt); + } + +// Given a successful reply from a server, create a new reply that contains lease information +// Replies are currently not signed !!!KRS change this +mDNSlocal PktMsg *FormatLeaseReply(DaemonInfo *d, PktMsg *orig, mDNSu32 lease) + { + PktMsg *reply; + mDNSu8 *ptr, *end; + mDNSOpaque16 flags; + + (void)d; //unused + reply = malloc(sizeof(*reply)); + if (!reply) { LogErr("FormatLeaseReply", "malloc"); return NULL; } + flags.b[0] = kDNSFlag0_QR_Response | kDNSFlag0_OP_Update; + flags.b[1] = 0; + + InitializeDNSMessage(&reply->msg.h, orig->msg.h.id, flags); + reply->src.sin_addr.s_addr = htonl(INADDR_ANY); // unused except for log messages + reply->src.sin_family = AF_INET; + ptr = reply->msg.data; + end = (mDNSu8 *)&reply->msg + sizeof(DNSMessage); + ptr = putUpdateLease(&reply->msg, ptr, lease); + if (!ptr) { Log("FormatLeaseReply: putUpdateLease failed"); free(reply); return NULL; } + reply->len = ptr - (mDNSu8 *)&reply->msg; + return reply; + } + +// pkt is thread-local, not requiring locking +mDNSlocal PktMsg *HandleRequest(PktMsg *pkt, DaemonInfo *d) + { + int sd = -1; + PktMsg *reply = NULL, *LeaseReply; + mDNSs32 lease; + char buf[32]; + + // send msg to server, read reply + sd = ConnectToServer(d); + if (sd < 0) + { Log("Discarding request from %s due to connection errors", inet_ntop(AF_INET, &pkt->src.sin_addr, buf, 32)); goto cleanup; } + if (SendTCPMsg(sd, pkt) < 0) + { Log("Couldn't relay message from %s to server. Discarding.", inet_ntop(AF_INET, &pkt->src.sin_addr, buf, 32)); goto cleanup; } + reply = ReadTCPMsg(sd, NULL); + + // process reply + if (!SuccessfulUpdateTransaction(pkt, reply)) + { VLog("Message from %s not a successful update.", inet_ntop(AF_INET, &pkt->src.sin_addr, buf, 32)); goto cleanup; } + lease = GetPktLease(pkt); + UpdateLeaseTable(pkt, d, lease); + if (lease > 0) + { + LeaseReply = FormatLeaseReply(d, reply, lease); + if (!LeaseReply) Log("HandleRequest - unable to format lease reply"); + free(reply); + reply = LeaseReply; + } + cleanup: + if (sd >= 0) close(sd); + return reply; + } + + +// +// LLQ Support Routines +// + +// Set fields of an LLQ Opt Resource Record +mDNSlocal void FormatLLQOpt(AuthRecord *opt, int opcode, mDNSu8 *id, mDNSs32 lease) + { + bzero(opt, sizeof(*opt)); + mDNS_SetupResourceRecord(opt, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, mDNSNULL, mDNSNULL); + opt->resrec.rdlength = LLQ_OPT_RDLEN; + opt->resrec.rdestimate = LLQ_OPT_RDLEN; + opt->resrec.rdata->u.opt.opt = kDNSOpt_LLQ; + opt->resrec.rdata->u.opt.optlen = sizeof(LLQOptData); + opt->resrec.rdata->u.opt.OptData.llq.vers = kLLQ_Vers; + opt->resrec.rdata->u.opt.OptData.llq.llqOp = opcode; + opt->resrec.rdata->u.opt.OptData.llq.err = LLQErr_NoError; + memcpy(opt->resrec.rdata->u.opt.OptData.llq.id, id, 8); + opt->resrec.rdata->u.opt.OptData.llq.lease = lease; + } + +// Calculate effective remaining lease of an LLQ +mDNSlocal mDNSu32 LLQLease(LLQEntry *e) + { + struct timeval t; + + gettimeofday(&t, NULL); + if (e->expire < t.tv_sec) return 0; + else return e->expire - t.tv_sec; + } + +mDNSlocal void DeleteLLQ(DaemonInfo *d, LLQEntry *e) + { + int bucket = DomainNameHashValue(&e->qname) % LLQ_TABLESIZE; + LLQEntry **ptr = &d->LLQTable[bucket]; + AnswerListElem *a = e->AnswerList; + char addr[32]; + + inet_ntop(AF_INET, &e->cli.sin_addr, addr, 32); + VLog("Deleting LLQ table entry for %##s client %s", e->qname.c, addr); + + // free shared answer structure if ref count drops to zero + if (a && !(--a->refcount)) + { + CacheRecord *cr = a->KnownAnswers, *tmp; + AnswerListElem **tbl = &d->AnswerTable[bucket]; + + while (cr) + { + tmp = cr; + cr = cr->next; + free(tmp); + } + + while (*tbl && *tbl != a) tbl = &(*tbl)->next; + if (*tbl) { *tbl = (*tbl)->next; free(a); } + else Log("Error: DeleteLLQ - AnswerList not found in table"); + } + + // remove LLQ from table, free memory + while(*ptr && *ptr != e) ptr = &(*ptr)->next; + if (!*ptr) { Log("Error: DeleteLLQ - LLQ not in table"); return; } + *ptr = (*ptr)->next; + free(e); + } + +mDNSlocal int SendLLQ(DaemonInfo *d, PktMsg *pkt, struct sockaddr_in dst) + { + char addr[32]; + int err = -1; + + HdrHToN(pkt); + if (sendto(d->udpsd, &pkt->msg, pkt->len, 0, (struct sockaddr *)&dst, sizeof(dst)) != (int)pkt->len) + { + LogErr("DaemonInfo", "sendto"); + Log("Could not send response to client %s", inet_ntop(AF_INET, &dst.sin_addr, addr, 32)); + } + else err = 0; + HdrNToH(pkt); + return err; + } + +// if non-negative, sd is a TCP socket connected to the nameserver +// otherwise, this routine creates and closes its own socket +mDNSlocal CacheRecord *AnswerQuestion(DaemonInfo *d, AnswerListElem *e, int sd) + { + PktMsg q; + int i; + const mDNSu8 *ansptr; + mDNSu8 *end = q.msg.data; + mDNSOpaque16 id, flags = QueryFlags; + PktMsg *reply = NULL; + LargeCacheRecord lcr; + CacheRecord *AnswerList = NULL; + mDNSu8 rcode; + mDNSBool CloseSDOnExit = sd < 0; + + VLog("Querying server for %##s type %d", e->name.c, e->type); + + flags.b[0] |= kDNSFlag0_RD; // recursion desired + id.NotAnInteger = 0; + InitializeDNSMessage(&q.msg.h, id, flags); + + end = putQuestion(&q.msg, end, end + AbsoluteMaxDNSMessageData, &e->name, e->type, kDNSClass_IN); + if (!end) { Log("Error: AnswerQuestion - putQuestion returned NULL"); goto end; } + q.len = (int)(end - (mDNSu8 *)&q.msg); + + if (sd < 0) sd = ConnectToServer(d); + if (sd < 0) { Log("AnswerQuestion: ConnectToServer failed"); goto end; } + if (SendTCPMsg(sd, &q)) { Log("AnswerQuestion: SendTCPMsg failed"); close(sd); goto end; } + reply = ReadTCPMsg(sd, NULL); + + if ((reply->msg.h.flags.b[0] & kDNSFlag0_QROP_Mask) != (kDNSFlag0_QR_Response | kDNSFlag0_OP_StdQuery)) + { Log("AnswerQuestion: %##s type %d - Invalid response flags from server"); goto end; } + rcode = (mDNSu8)(reply->msg.h.flags.b[1] & kDNSFlag1_RC); + if (rcode && rcode != kDNSFlag1_RC_NXDomain) { Log("AnswerQuestion: %##s type %d - non-zero rcode %d from server", e->name.c, e->type, rcode); goto end; } + + end = (mDNSu8 *)&reply->msg + reply->len; + ansptr = LocateAnswers(&reply->msg, end); + if (!ansptr) { Log("Error: AnswerQuestion - LocateAnswers returned NULL"); goto end; } + + for (i = 0; i < reply->msg.h.numAnswers; i++) + { + ansptr = GetLargeResourceRecord(NULL, &reply->msg, ansptr, end, 0, kDNSRecordTypePacketAns, &lcr); + if (!ansptr) { Log("AnswerQuestions: GetLargeResourceRecord returned NULL"); goto end; } + if (lcr.r.resrec.rrtype != e->type || lcr.r.resrec.rrclass != kDNSClass_IN || !SameDomainName(lcr.r.resrec.name, &e->name)) + { + Log("AnswerQuestion: response %##s type #d does not answer question %##s type #d. Discarding", + lcr.r.resrec.name->c, lcr.r.resrec.rrtype, e->name.c, e->type); + } + else + { + CacheRecord *cr = CopyCacheRecord(&lcr.r, &e->name); + if (!cr) { Log("Error: AnswerQuestion - CopyCacheRecord returned NULL"); goto end; } + cr->next = AnswerList; + AnswerList = cr; + } + } + + end: + if (sd > -1 && CloseSDOnExit) close(sd); + if (reply) free(reply); + return AnswerList; + } + +// Routine sets EventList to contain Add/Remove events, and deletes any removes from the KnownAnswer list +mDNSlocal void UpdateAnswerList(DaemonInfo *d, AnswerListElem *a, int sd) + { + CacheRecord *cr, *NewAnswers, **na, **ka; // "new answer", "known answer" + + // get up to date answers + NewAnswers = AnswerQuestion(d, a, sd); + + // first pass - mark all answers for deletion + for (ka = &a->KnownAnswers; *ka; ka = &(*ka)->next) + (*ka)->resrec.rroriginalttl = (unsigned)-1; // -1 means delete + + // second pass - mark answers pre-existent + for (ka = &a->KnownAnswers; *ka; ka = &(*ka)->next) + { + for (na = &NewAnswers; *na; na = &(*na)->next) + { + if (SameResourceRecord(&(*ka)->resrec, &(*na)->resrec)) + { (*ka)->resrec.rroriginalttl = 0; break; } // 0 means no change + } + } + + // third pass - add new records to Event list + na = &NewAnswers; + while (*na) + { + for (ka = &a->KnownAnswers; *ka; ka = &(*ka)->next) + if (SameResourceRecord(&(*ka)->resrec, &(*na)->resrec)) break; + if (!*ka) + { + // answer is not in list - splice from NewAnswers list, add to Event list + cr = *na; + *na = (*na)->next; // splice from list + cr->next = a->EventList; // add spliced record to event list + a->EventList = cr; + cr->resrec.rroriginalttl = 1; // 1 means add + } + else na = &(*na)->next; + } + + // move all the removes from the answer list to the event list + ka = &a->KnownAnswers; + while (*ka) + { + if ((*ka)->resrec.rroriginalttl == (unsigned)-1) + { + cr = *ka; + *ka = (*ka)->next; + cr->next = a->EventList; + a->EventList = cr; + } + else ka = &(*ka)->next; + } + + // lastly, free the remaining records (known answers) in NewAnswers list + while (NewAnswers) + { + cr = NewAnswers; + NewAnswers = NewAnswers->next; + free(cr); + } + } + +mDNSlocal void SendEvents(DaemonInfo *d, LLQEntry *e) + { + PktMsg response; + CacheRecord *cr; + mDNSu8 *end = (mDNSu8 *)&response.msg.data; + mDNSOpaque16 msgID; + char rrbuf[80], addrbuf[32]; + AuthRecord opt; + + msgID.NotAnInteger = random(); + if (verbose) inet_ntop(AF_INET, &e->cli.sin_addr, addrbuf, 32); + InitializeDNSMessage(&response.msg.h, msgID, ResponseFlags); + end = putQuestion(&response.msg, end, end + AbsoluteMaxDNSMessageData, &e->qname, e->qtype, kDNSClass_IN); + if (!end) { Log("Error: SendEvents - putQuestion returned NULL"); return; } + + // put adds/removes in packet + for (cr = e->AnswerList->EventList; cr; cr = cr->next) + { + if (verbose) GetRRDisplayString_rdb(&cr->resrec, &cr->resrec.rdata->u, rrbuf); + VLog("%s (%s): %s", addrbuf, (mDNSs32)cr->resrec.rroriginalttl < 0 ? "Remove": "Add", rrbuf); + end = PutResourceRecordTTLJumbo(&response.msg, end, &response.msg.h.numAnswers, &cr->resrec, cr->resrec.rroriginalttl); + if (!end) { Log("Error: SendEvents - UpdateAnswerList returned NULL"); return; } + } + + FormatLLQOpt(&opt, kLLQOp_Event, e->id, LLQLease(e)); + end = PutResourceRecordTTLJumbo(&response.msg, end, &response.msg.h.numAdditionals, &opt.resrec, 0); + if (!end) { Log("Error: SendEvents - PutResourceRecordTTLJumbo"); return; } + + response.len = (int)(end - (mDNSu8 *)&response.msg); + if (SendLLQ(d, &response, e->cli) < 0) LogMsg("Error: SendEvents - SendLLQ"); + } + +mDNSlocal void PrintLLQTable(DaemonInfo *d) + { + LLQEntry *e; + char addr[32]; + int i; + + Log("Printing LLQ table contents"); + + for (i = 0; i < LLQ_TABLESIZE; i++) + { + e = d->LLQTable[i]; + while(e) + { + inet_ntop(AF_INET, &e->cli.sin_addr, addr, 32); + Log("LLQ from %##s type %d lease %d (%d remaining)", + addr, e->qname.c, e->qtype, e->lease, LLQLease(e)); + e = e->next; + } + } + } + +// Send events to clients as a result of a change in the zone +mDNSlocal void GenLLQEvents(DaemonInfo *d) + { + LLQEntry **e; + int i, sd; + struct timeval t; + + VLog("Generating LLQ Events"); + + gettimeofday(&t, NULL); + sd = ConnectToServer(d); + if (sd < 0) { Log("GenLLQEvents: ConnectToServer failed"); return; } + + // get all answers up to date + for (i = 0; i < LLQ_TABLESIZE; i++) + { + AnswerListElem *a = d->AnswerTable[i]; + while(a) + { + UpdateAnswerList(d, a, sd); + a = a->next; + } + } + + // for each established LLQ, send events + for (i = 0; i < LLQ_TABLESIZE; i++) + { + e = &d->LLQTable[i]; + while(*e) + { + if ((*e)->expire < t.tv_sec) DeleteLLQ(d, *e); + else + { + if ((*e)->state == Established && (*e)->AnswerList->EventList) SendEvents(d, *e); + e = &(*e)->next; + } + } + } + + // now that all LLQs are updated, we move Add events from the Event list to the Known Answer list, and free Removes + for (i = 0; i < LLQ_TABLESIZE; i++) + { + AnswerListElem *a = d->AnswerTable[i]; + while(a) + { + if (a->EventList) + { + CacheRecord *cr = a->EventList, *tmp; + while (cr) + { + tmp = cr; + cr = cr->next; + if ((signed)tmp->resrec.rroriginalttl < 0) free(tmp); + else + { + tmp->next = a->KnownAnswers; + a->KnownAnswers = tmp; + tmp->resrec.rroriginalttl = 0; + } + } + a->EventList = NULL; + } + a = a->next; + } + } + + close(sd); + } + +// Monitor zone for changes that may produce LLQ events +mDNSlocal void *LLQEventMonitor(void *DInfoPtr) + { + DaemonInfo *d = DInfoPtr; + PktMsg q; + mDNSu8 *end = q.msg.data; + const mDNSu8 *ptr; + mDNSOpaque16 id, flags = QueryFlags; + PktMsg reply; + mDNSs32 serial = 0; + mDNSBool SerialInitialized = mDNSfalse; + int sd; + LargeCacheRecord lcr; + ResourceRecord *rr = &lcr.r.resrec; + int i, sleeptime = 0; + domainname zone; + char pingmsg[4]; + + // create question + id.NotAnInteger = 0; + InitializeDNSMessage(&q.msg.h, id, flags); + AssignDomainName(&zone, &d->zone); + end = putQuestion(&q.msg, end, end + AbsoluteMaxDNSMessageData, &zone, kDNSType_SOA, kDNSClass_IN); + if (!end) { Log("Error: LLQEventMonitor - putQuestion returned NULL"); return NULL; } + q.len = (int)(end - (mDNSu8 *)&q.msg); + + sd = ConnectToServer(d); + if (sd < 0) { Log("LLQEventMonitor: ConnectToServer failed"); return NULL; } + + while(1) + { + usleep(sleeptime); + sleeptime = LLQ_MONITOR_ERR_INTERVAL; // if we bail on error below, rate limit retry + + // send message, receive response + if (SendTCPMsg(sd, &q)) { Log("LLQEventMonitor: SendTCPMsg failed"); continue; } + if (!ReadTCPMsg(sd, &reply)) { Log("LLQEventMonitor: ReadTCPMsg failed"); continue; } + end = (mDNSu8 *)&reply.msg + reply.len; + if (reply.msg.h.flags.b[1] & kDNSFlag1_RC) { Log("LLQEventMonitor - received non-zero rcode"); continue; } + + // find answer + ptr = LocateAnswers(&reply.msg, end); + if (!ptr) { Log("Error: LLQEventMonitor - LocateAnswers returned NULL"); continue; } + for (i = 0; i < reply.msg.h.numAnswers; i++) + { + ptr = GetLargeResourceRecord(NULL, &reply.msg, ptr, end, 0, kDNSRecordTypePacketAns, &lcr); + if (!ptr) { Log("Error: LLQEventMonitor - GetLargeResourceRecord returned NULL"); continue; } + if (rr->rrtype != kDNSType_SOA || rr->rrclass != kDNSClass_IN || !SameDomainName(rr->name, &zone)) continue; + if (!SerialInitialized) + { + // first time through loop + SerialInitialized = mDNStrue; + serial = rr->rdata->u.soa.serial; + sleeptime = LLQ_MONITOR_INTERVAL; + break; + } + else if (rr->rdata->u.soa.serial != serial) + { + // update serial, wake main thread + serial = rr->rdata->u.soa.serial; + VLog("LLQEventMonitor: zone changed. Signaling main thread."); + if (send(d->LLQServPollSock, pingmsg, sizeof(pingmsg), 0) != sizeof(pingmsg)) + { LogErr("LLQEventMonitor", "send"); break; } + } + sleeptime = LLQ_MONITOR_INTERVAL; + break; + } + if (!ptr) Log("LLQEventMonitor: response to query did not contain SOA"); + } + } + +mDNSlocal void SetAnswerList(DaemonInfo *d, LLQEntry *e) + { + int bucket = DomainNameHashValue(&e->qname) % LLQ_TABLESIZE; + AnswerListElem *a = d->AnswerTable[bucket]; + while (a && (a->type != e->qtype ||!SameDomainName(&a->name, &e->qname))) a = a->next; + if (!a) + { + a = malloc(sizeof(*a)); + if (!a) { LogErr("SetAnswerList", "malloc"); return; } + AssignDomainName(&a->name, &e->qname); + a->type = e->qtype; + a->refcount = 0; + a->KnownAnswers = NULL; + a->EventList = NULL; + a->next = d->AnswerTable[bucket]; + d->AnswerTable[bucket] = a; + + // to get initial answer list, call UpdateAnswerList and move cache records from EventList to KnownAnswers + UpdateAnswerList(d, a, -1); + a->KnownAnswers = a->EventList; + a->EventList = NULL; + } + + e->AnswerList = a; + a->refcount ++; + } + + // Allocate LLQ entry, insert into table +mDNSlocal LLQEntry *NewLLQ(DaemonInfo *d, struct sockaddr_in cli, domainname *qname, mDNSu16 qtype, mDNSu32 lease) + { + char addr[32]; + struct timeval t; + int bucket = DomainNameHashValue(qname) % LLQ_TABLESIZE; + LLQEntry *e; + + e = malloc(sizeof(*e)); + if (!e) { LogErr("NewLLQ", "malloc"); return NULL; } + + inet_ntop(AF_INET, &cli.sin_addr, addr, 32); + VLog("Allocating LLQ entry for client %s question %##s type %d", addr, qname->c, qtype); + + // initialize structure + e->cli = cli; + AssignDomainName(&e->qname, qname); + e->qtype = qtype; + memset(e->id, 0, 8); + e->state = RequestReceived; + e->AnswerList = NULL; + + if (lease < LLQ_MIN_LEASE) lease = LLQ_MIN_LEASE; + else if (lease > LLQ_MAX_LEASE) lease = LLQ_MIN_LEASE; + gettimeofday(&t, NULL); + e->expire = t.tv_sec + (int)lease; + e->lease = lease; + + // add to table + e->next = d->LLQTable[bucket]; + d->LLQTable[bucket] = e; + + return e; + } + +// Handle a refresh request from client +mDNSlocal void LLQRefresh(DaemonInfo *d, LLQEntry *e, LLQOptData *llq, mDNSOpaque16 msgID) + { + AuthRecord opt; + PktMsg ack; + mDNSu8 *end = (mDNSu8 *)&ack.msg.data; + char addr[32]; + + inet_ntop(AF_INET, &e->cli.sin_addr, addr, 32); + VLog("%s LLQ for %##s from %s", llq->lease ? "Refreshing" : "Deleting", e->qname.c, addr); + + if (llq->lease) + { + if (llq->lease < LLQ_MIN_LEASE) llq->lease = LLQ_MIN_LEASE; + else if (llq->lease > LLQ_MAX_LEASE) llq->lease = LLQ_MIN_LEASE; + } + + ack.src.sin_addr.s_addr = 0; // unused + InitializeDNSMessage(&ack.msg.h, msgID, ResponseFlags); + end = putQuestion(&ack.msg, end, end + AbsoluteMaxDNSMessageData, &e->qname, e->qtype, kDNSClass_IN); + if (!end) { Log("Error: putQuestion"); return; } + + FormatLLQOpt(&opt, kLLQOp_Refresh, e->id, llq->lease ? LLQLease(e) : 0); + end = PutResourceRecordTTLJumbo(&ack.msg, end, &ack.msg.h.numAdditionals, &opt.resrec, 0); + if (!end) { Log("Error: PutResourceRecordTTLJumbo"); return; } + + ack.len = (int)(end - (mDNSu8 *)&ack.msg); + if (SendLLQ(d, &ack, e->cli)) Log("Error: LLQRefresh"); + + if (llq->lease) e->state = Established; + else DeleteLLQ(d, e); + } + +// Complete handshake with Ack an initial answers +mDNSlocal void LLQCompleteHandshake(DaemonInfo *d, LLQEntry *e, LLQOptData *llq, mDNSOpaque16 msgID) + { + char addr[32]; + CacheRecord *ptr; + AuthRecord opt; + PktMsg ack; + mDNSu8 *end = (mDNSu8 *)&ack.msg.data; + char rrbuf[80], addrbuf[32]; + + inet_ntop(AF_INET, &e->cli.sin_addr, addr, 32); + + if (memcmp(llq->id, e->id, 8) || + llq->vers != kLLQ_Vers || + llq->llqOp != kLLQOp_Setup || + llq->err != LLQErr_NoError || + llq->lease > e->lease + LLQ_LEASE_FUDGE || + llq->lease < e->lease - LLQ_LEASE_FUDGE) + { Log("Incorrect challenge response from %s", addr); return; } + + if (e->state == Established) VLog("Retransmitting LLQ ack + answers for %##s", e->qname.c); + else VLog("Delivering LLQ ack + answers for %##s", e->qname.c); + + // format ack + answers + ack.src.sin_addr.s_addr = 0; // unused + InitializeDNSMessage(&ack.msg.h, msgID, ResponseFlags); + end = putQuestion(&ack.msg, end, end + AbsoluteMaxDNSMessageData, &e->qname, e->qtype, kDNSClass_IN); + if (!end) { Log("Error: putQuestion"); return; } + + if (e->state != Established) { SetAnswerList(d, e); e->state = Established; } + + if (verbose) inet_ntop(AF_INET, &e->cli.sin_addr, addrbuf, 32); + for (ptr = e->AnswerList->KnownAnswers; ptr; ptr = ptr->next) + { + if (verbose) GetRRDisplayString_rdb(&ptr->resrec, &ptr->resrec.rdata->u, rrbuf); + VLog("%s Intitial Answer - %s", addr, rrbuf); + end = PutResourceRecordTTLJumbo(&ack.msg, end, &ack.msg.h.numAnswers, &ptr->resrec, 1); + if (!end) { Log("Error: PutResourceRecordTTLJumbo"); return; } + } + + FormatLLQOpt(&opt, kLLQOp_Setup, e->id, LLQLease(e)); + end = PutResourceRecordTTLJumbo(&ack.msg, end, &ack.msg.h.numAdditionals, &opt.resrec, 0); + if (!end) { Log("Error: PutResourceRecordTTLJumbo"); return; } + + ack.len = (int)(end - (mDNSu8 *)&ack.msg); + if (SendLLQ(d, &ack, e->cli)) Log("Error: LLQCompleteHandshake"); + } + +mDNSlocal void LLQSetupChallenge(DaemonInfo *d, LLQEntry *e, LLQOptData *llq, mDNSOpaque16 msgID) + { + struct timeval t; + mDNSu32 randval; + PktMsg challenge; + mDNSu8 *end = challenge.msg.data; + AuthRecord opt; + + if (e->state == ChallengeSent) VLog("Retransmitting LLQ setup challenge for %##s", e->qname.c); + else VLog("Sending LLQ setup challenge for %##s", e->qname.c); + + if (!ZERO_LLQID(llq->id)) { Log("Error: LLQSetupChallenge - nonzero ID"); return; } // server bug + if (llq->llqOp != kLLQOp_Setup) { Log("LLQSetupChallenge - incorrrect operation from client"); return; } // client error + + if (ZERO_LLQID(e->id)) // don't regenerate random ID for retransmissions + { + // construct ID