2 * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
23 Change History (most recent first):
26 Revision 1.9 2003/08/14 02:19:55 cheshire
27 <rdar://problem/3375491> Split generic ResourceRecord type into two separate types: AuthRecord and CacheRecord
29 Revision 1.8 2003/08/12 19:56:26 cheshire
32 Revision 1.7 2003/07/02 21:19:58 cheshire
33 <rdar://problem/3313413> Update copyright notices, etc., in source code comments
35 Revision 1.6 2003/06/18 05:48:41 cheshire
38 Revision 1.5 2003/05/06 00:00:50 cheshire
39 <rdar://problem/3248914> Rationalize naming of domainname manipulation functions
41 Revision 1.4 2002/12/23 22:13:31 jgraessl
43 Reviewed by: Stuart Cheshire
44 Initial IPv6 support for mDNSResponder.
46 Revision 1.3 2002/09/21 20:44:53 zarzycki
49 Revision 1.2 2002/09/19 04:20:44 cheshire
50 Remove high-ascii characters that confuse some systems
52 Revision 1.1 2002/09/17 06:24:35 cheshire
64 #include "mDNSClientAPI.h"// Defines the interface to the mDNS core code
65 #include "mDNSPosix.h" // Defines the specific types needed to run mDNS on this platform
66 #include "ExampleClientApp.h"
69 static mDNS mDNSStorage
; // mDNS core uses this to store its globals
70 static mDNS_PlatformSupport PlatformStorage
; // Stores this platform's globals
71 #define RR_CACHE_SIZE 500
72 static CacheRecord gRRCache
[RR_CACHE_SIZE
];
74 static const char *gProgramName
= "mDNSResponderPosix";
76 static void BrowseCallback(mDNS
*const m
, DNSQuestion
*question
, const ResourceRecord
*const answer
, mDNSBool AddRecord
)
77 // A callback from the core mDNS code that indicates that we've received a
78 // response to our query. Note that this code runs on the main thread
79 // (in fact, there is only one thread!), so we can safely printf the results.
90 (void)question
; // Unused
92 assert(answer
->rrtype
== kDNSType_PTR
);
94 DeconstructServiceName(&answer
->rdata
->u
.name
, &name
, &type
, &domain
);
96 ConvertDomainLabelToCString_unescaped(&name
, nameC
);
97 ConvertDomainNameToCString(&type
, typeC
);
98 ConvertDomainNameToCString(&domain
, domainC
);
100 // If the TTL has hit 0, the service is no longer available.
106 fprintf(stderr
, "*** %s name = '%s', type = '%s', domain = '%s'\n", state
, nameC
, typeC
, domainC
);
109 static mDNSBool
CheckThatServiceTypeIsUsable(const char *serviceType
, mDNSBool printExplanation
)
110 // Checks that serviceType is a reasonable service type
111 // label and, if it isn't and printExplanation is true, prints
112 // an explanation of why not.
117 if (result
&& strlen(serviceType
) > 63) {
118 if (printExplanation
) {
120 "%s: Service type specified by -t is too long (must be 63 characters or less)\n",
125 if (result
&& serviceType
[0] == 0) {
126 if (printExplanation
) {
128 "%s: Service type specified by -t can't be empty\n",
136 static const char kDefaultServiceType
[] = "_afpovertcp._tcp.";
138 static void PrintUsage()
141 "Usage: %s [-v level] [-t type]\n",
143 fprintf(stderr
, " -v verbose mode, level is a number from 0 to 2\n");
144 fprintf(stderr
, " 0 = no debugging info (default)\n");
145 fprintf(stderr
, " 1 = standard debugging info\n");
146 fprintf(stderr
, " 2 = intense debugging info\n");
147 fprintf(stderr
, " -t uses 'type' as the service type (default is '%s')\n", kDefaultServiceType
);
150 static const char *gServiceType
= kDefaultServiceType
;
152 static void ParseArguments(int argc
, char **argv
)
153 // Parses our command line arguments into the global variables
158 // Set gProgramName to the last path component of argv[0]
160 gProgramName
= strrchr(argv
[0], '/');
161 if (gProgramName
== NULL
) {
162 gProgramName
= argv
[0];
167 // Parse command line options using getopt.
170 ch
= getopt(argc
, argv
, "v:t:");
174 gMDNSPlatformPosixVerboseLevel
= atoi(optarg
);
175 if (gMDNSPlatformPosixVerboseLevel
< 0 || gMDNSPlatformPosixVerboseLevel
> 2) {
177 "%s: Verbose mode must be in the range 0..2\n",
183 gServiceType
= optarg
;
184 if ( ! CheckThatServiceTypeIsUsable(gServiceType
, mDNStrue
) ) {
197 // Check for any left over command line arguments.
199 if (optind
!= argc
) {
200 fprintf(stderr
, "%s: Unexpected argument '%s'\n", gProgramName
, argv
[optind
]);
205 int main(int argc
, char **argv
)
206 // The program's main entry point. The program does a trivial
207 // mDNS query, looking for all AFP servers in the local domain.
211 DNSQuestion question
;
215 // Parse our command line arguments. This won't come back if there's an error.
216 ParseArguments(argc
, argv
);
218 // Initialise the mDNS core.
219 status
= mDNS_Init(&mDNSStorage
, &PlatformStorage
,
220 gRRCache
, RR_CACHE_SIZE
,
221 mDNS_Init_DontAdvertiseLocalAddresses
,
222 mDNS_Init_NoInitCallback
, mDNS_Init_NoInitCallbackContext
);
223 if (status
== mStatus_NoError
) {
225 // Construct and start the query.
227 MakeDomainNameFromDNSNameString(&type
, gServiceType
);
228 MakeDomainNameFromDNSNameString(&domain
, "local.");
230 status
= mDNS_StartBrowse(&mDNSStorage
, &question
, &type
, &domain
, mDNSInterface_Any
, BrowseCallback
, NULL
);
232 // Run the platform main event loop until the user types ^C.
233 // The BrowseCallback routine is responsible for printing
234 // any results that we find.
236 if (status
== mStatus_NoError
) {
237 fprintf(stderr
, "Hit ^C when you're bored waiting for responses.\n");
238 ExampleClientEventLoop(&mDNSStorage
);
239 mDNS_StopQuery(&mDNSStorage
, &question
);
240 mDNS_Close(&mDNSStorage
);
244 if (status
== mStatus_NoError
) {
249 if ( (result
!= 0) || (gMDNSPlatformPosixVerboseLevel
> 0) ) {
250 fprintf(stderr
, "%s: Finished with status %ld, result %d\n", gProgramName
, status
, result
);