1*48a54d36SAndroid Build Coastguard Worker /* -*- Mode: C; tab-width: 4 -*-
2*48a54d36SAndroid Build Coastguard Worker *
3*48a54d36SAndroid Build Coastguard Worker * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
4*48a54d36SAndroid Build Coastguard Worker *
5*48a54d36SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
6*48a54d36SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
7*48a54d36SAndroid Build Coastguard Worker * You may obtain a copy of the License at
8*48a54d36SAndroid Build Coastguard Worker *
9*48a54d36SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
10*48a54d36SAndroid Build Coastguard Worker *
11*48a54d36SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
12*48a54d36SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
13*48a54d36SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*48a54d36SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
15*48a54d36SAndroid Build Coastguard Worker * limitations under the License.
16*48a54d36SAndroid Build Coastguard Worker */
17*48a54d36SAndroid Build Coastguard Worker
18*48a54d36SAndroid Build Coastguard Worker #if __APPLE__
19*48a54d36SAndroid Build Coastguard Worker // In Mac OS X 10.5 and later trying to use the daemon function gives a “‘daemon’ is deprecated”
20*48a54d36SAndroid Build Coastguard Worker // error, which prevents compilation because we build with "-Werror".
21*48a54d36SAndroid Build Coastguard Worker // Since this is supposed to be portable cross-platform code, we don't care that daemon is
22*48a54d36SAndroid Build Coastguard Worker // deprecated on Mac OS X 10.5, so we use this preprocessor trick to eliminate the error message.
23*48a54d36SAndroid Build Coastguard Worker #define daemon yes_we_know_that_daemon_is_deprecated_in_os_x_10_5_thankyou
24*48a54d36SAndroid Build Coastguard Worker #endif
25*48a54d36SAndroid Build Coastguard Worker
26*48a54d36SAndroid Build Coastguard Worker #include <assert.h>
27*48a54d36SAndroid Build Coastguard Worker #include <stdio.h> // For printf()
28*48a54d36SAndroid Build Coastguard Worker #include <stdlib.h> // For exit() etc.
29*48a54d36SAndroid Build Coastguard Worker #include <string.h> // For strlen() etc.
30*48a54d36SAndroid Build Coastguard Worker #include <unistd.h> // For select()
31*48a54d36SAndroid Build Coastguard Worker #include <errno.h> // For errno, EINTR
32*48a54d36SAndroid Build Coastguard Worker #include <signal.h>
33*48a54d36SAndroid Build Coastguard Worker #include <fcntl.h>
34*48a54d36SAndroid Build Coastguard Worker
35*48a54d36SAndroid Build Coastguard Worker #if __APPLE__
36*48a54d36SAndroid Build Coastguard Worker #undef daemon
37*48a54d36SAndroid Build Coastguard Worker extern int daemon(int, int);
38*48a54d36SAndroid Build Coastguard Worker #endif
39*48a54d36SAndroid Build Coastguard Worker
40*48a54d36SAndroid Build Coastguard Worker #include "mDNSEmbeddedAPI.h"// Defines the interface to the client layer above
41*48a54d36SAndroid Build Coastguard Worker #include "mDNSPosix.h" // Defines the specific types needed to run mDNS on this platform
42*48a54d36SAndroid Build Coastguard Worker #include "mDNSUNP.h" // For daemon()
43*48a54d36SAndroid Build Coastguard Worker
44*48a54d36SAndroid Build Coastguard Worker #if COMPILER_LIKES_PRAGMA_MARK
45*48a54d36SAndroid Build Coastguard Worker #pragma mark ***** Globals
46*48a54d36SAndroid Build Coastguard Worker #endif
47*48a54d36SAndroid Build Coastguard Worker
48*48a54d36SAndroid Build Coastguard Worker static mDNS mDNSStorage; // mDNS core uses this to store its globals
49*48a54d36SAndroid Build Coastguard Worker static mDNS_PlatformSupport PlatformStorage; // Stores this platform's globals
50*48a54d36SAndroid Build Coastguard Worker
51*48a54d36SAndroid Build Coastguard Worker mDNSexport const char ProgramName[] = "mDNSResponderPosix";
52*48a54d36SAndroid Build Coastguard Worker
53*48a54d36SAndroid Build Coastguard Worker static const char *gProgramName = ProgramName;
54*48a54d36SAndroid Build Coastguard Worker
55*48a54d36SAndroid Build Coastguard Worker #if COMPILER_LIKES_PRAGMA_MARK
56*48a54d36SAndroid Build Coastguard Worker #pragma mark ***** Signals
57*48a54d36SAndroid Build Coastguard Worker #endif
58*48a54d36SAndroid Build Coastguard Worker
59*48a54d36SAndroid Build Coastguard Worker static volatile mDNSBool gReceivedSigUsr1;
60*48a54d36SAndroid Build Coastguard Worker static volatile mDNSBool gReceivedSigHup;
61*48a54d36SAndroid Build Coastguard Worker static volatile mDNSBool gStopNow;
62*48a54d36SAndroid Build Coastguard Worker
63*48a54d36SAndroid Build Coastguard Worker // We support 4 signals.
64*48a54d36SAndroid Build Coastguard Worker //
65*48a54d36SAndroid Build Coastguard Worker // o SIGUSR1 toggles verbose mode on and off in debug builds
66*48a54d36SAndroid Build Coastguard Worker // o SIGHUP triggers the program to re-read its preferences.
67*48a54d36SAndroid Build Coastguard Worker // o SIGINT causes an orderly shutdown of the program.
68*48a54d36SAndroid Build Coastguard Worker // o SIGQUIT causes a somewhat orderly shutdown (direct but dangerous)
69*48a54d36SAndroid Build Coastguard Worker // o SIGKILL kills us dead (easy to implement :-)
70*48a54d36SAndroid Build Coastguard Worker //
71*48a54d36SAndroid Build Coastguard Worker // There are fatal race conditions in our signal handling, but there's not much
72*48a54d36SAndroid Build Coastguard Worker // we can do about them while remaining within the Posix space. Specifically,
73*48a54d36SAndroid Build Coastguard Worker // if a signal arrives after we test the globals its sets but before we call
74*48a54d36SAndroid Build Coastguard Worker // select, the signal will be dropped. The user will have to send the signal
75*48a54d36SAndroid Build Coastguard Worker // again. Unfortunately, Posix does not have a "sigselect" to atomically
76*48a54d36SAndroid Build Coastguard Worker // modify the signal mask and start a select.
77*48a54d36SAndroid Build Coastguard Worker
HandleSigUsr1(int sigraised)78*48a54d36SAndroid Build Coastguard Worker static void HandleSigUsr1(int sigraised)
79*48a54d36SAndroid Build Coastguard Worker // If we get a SIGUSR1 we toggle the state of the
80*48a54d36SAndroid Build Coastguard Worker // verbose mode.
81*48a54d36SAndroid Build Coastguard Worker {
82*48a54d36SAndroid Build Coastguard Worker assert(sigraised == SIGUSR1);
83*48a54d36SAndroid Build Coastguard Worker gReceivedSigUsr1 = mDNStrue;
84*48a54d36SAndroid Build Coastguard Worker }
85*48a54d36SAndroid Build Coastguard Worker
HandleSigHup(int sigraised)86*48a54d36SAndroid Build Coastguard Worker static void HandleSigHup(int sigraised)
87*48a54d36SAndroid Build Coastguard Worker // A handler for SIGHUP that causes us to break out of the
88*48a54d36SAndroid Build Coastguard Worker // main event loop when the user kill 1's us. This has the
89*48a54d36SAndroid Build Coastguard Worker // effect of triggered the main loop to deregister the
90*48a54d36SAndroid Build Coastguard Worker // current services and re-read the preferences.
91*48a54d36SAndroid Build Coastguard Worker {
92*48a54d36SAndroid Build Coastguard Worker assert(sigraised == SIGHUP);
93*48a54d36SAndroid Build Coastguard Worker gReceivedSigHup = mDNStrue;
94*48a54d36SAndroid Build Coastguard Worker }
95*48a54d36SAndroid Build Coastguard Worker
HandleSigInt(int sigraised)96*48a54d36SAndroid Build Coastguard Worker static void HandleSigInt(int sigraised)
97*48a54d36SAndroid Build Coastguard Worker // A handler for SIGINT that causes us to break out of the
98*48a54d36SAndroid Build Coastguard Worker // main event loop when the user types ^C. This has the
99*48a54d36SAndroid Build Coastguard Worker // effect of quitting the program.
100*48a54d36SAndroid Build Coastguard Worker {
101*48a54d36SAndroid Build Coastguard Worker assert(sigraised == SIGINT);
102*48a54d36SAndroid Build Coastguard Worker
103*48a54d36SAndroid Build Coastguard Worker if (gMDNSPlatformPosixVerboseLevel > 0) {
104*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "\nSIGINT\n");
105*48a54d36SAndroid Build Coastguard Worker }
106*48a54d36SAndroid Build Coastguard Worker gStopNow = mDNStrue;
107*48a54d36SAndroid Build Coastguard Worker }
108*48a54d36SAndroid Build Coastguard Worker
HandleSigQuit(int sigraised)109*48a54d36SAndroid Build Coastguard Worker static void HandleSigQuit(int sigraised)
110*48a54d36SAndroid Build Coastguard Worker // If we get a SIGQUIT the user is desperate and we
111*48a54d36SAndroid Build Coastguard Worker // just call mDNS_Close directly. This is definitely
112*48a54d36SAndroid Build Coastguard Worker // not safe (because it could reenter mDNS), but
113*48a54d36SAndroid Build Coastguard Worker // we presume that the user has already tried the safe
114*48a54d36SAndroid Build Coastguard Worker // alternatives.
115*48a54d36SAndroid Build Coastguard Worker {
116*48a54d36SAndroid Build Coastguard Worker assert(sigraised == SIGQUIT);
117*48a54d36SAndroid Build Coastguard Worker
118*48a54d36SAndroid Build Coastguard Worker if (gMDNSPlatformPosixVerboseLevel > 0) {
119*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "\nSIGQUIT\n");
120*48a54d36SAndroid Build Coastguard Worker }
121*48a54d36SAndroid Build Coastguard Worker mDNS_Close(&mDNSStorage);
122*48a54d36SAndroid Build Coastguard Worker exit(0);
123*48a54d36SAndroid Build Coastguard Worker }
124*48a54d36SAndroid Build Coastguard Worker
125*48a54d36SAndroid Build Coastguard Worker #if COMPILER_LIKES_PRAGMA_MARK
126*48a54d36SAndroid Build Coastguard Worker #pragma mark ***** Parameter Checking
127*48a54d36SAndroid Build Coastguard Worker #endif
128*48a54d36SAndroid Build Coastguard Worker
CheckThatRichTextNameIsUsable(const char * richTextName,mDNSBool printExplanation)129*48a54d36SAndroid Build Coastguard Worker static mDNSBool CheckThatRichTextNameIsUsable(const char *richTextName, mDNSBool printExplanation)
130*48a54d36SAndroid Build Coastguard Worker // Checks that richTextName is reasonable
131*48a54d36SAndroid Build Coastguard Worker // label and, if it isn't and printExplanation is true, prints
132*48a54d36SAndroid Build Coastguard Worker // an explanation of why not.
133*48a54d36SAndroid Build Coastguard Worker {
134*48a54d36SAndroid Build Coastguard Worker mDNSBool result = mDNStrue;
135*48a54d36SAndroid Build Coastguard Worker if (result && strlen(richTextName) > 63) {
136*48a54d36SAndroid Build Coastguard Worker if (printExplanation) {
137*48a54d36SAndroid Build Coastguard Worker fprintf(stderr,
138*48a54d36SAndroid Build Coastguard Worker "%s: Service name is too long (must be 63 characters or less)\n",
139*48a54d36SAndroid Build Coastguard Worker gProgramName);
140*48a54d36SAndroid Build Coastguard Worker }
141*48a54d36SAndroid Build Coastguard Worker result = mDNSfalse;
142*48a54d36SAndroid Build Coastguard Worker }
143*48a54d36SAndroid Build Coastguard Worker if (result && richTextName[0] == 0) {
144*48a54d36SAndroid Build Coastguard Worker if (printExplanation) {
145*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "%s: Service name can't be empty\n", gProgramName);
146*48a54d36SAndroid Build Coastguard Worker }
147*48a54d36SAndroid Build Coastguard Worker result = mDNSfalse;
148*48a54d36SAndroid Build Coastguard Worker }
149*48a54d36SAndroid Build Coastguard Worker return result;
150*48a54d36SAndroid Build Coastguard Worker }
151*48a54d36SAndroid Build Coastguard Worker
CheckThatServiceTypeIsUsable(const char * serviceType,mDNSBool printExplanation)152*48a54d36SAndroid Build Coastguard Worker static mDNSBool CheckThatServiceTypeIsUsable(const char *serviceType, mDNSBool printExplanation)
153*48a54d36SAndroid Build Coastguard Worker // Checks that serviceType is a reasonable service type
154*48a54d36SAndroid Build Coastguard Worker // label and, if it isn't and printExplanation is true, prints
155*48a54d36SAndroid Build Coastguard Worker // an explanation of why not.
156*48a54d36SAndroid Build Coastguard Worker {
157*48a54d36SAndroid Build Coastguard Worker mDNSBool result;
158*48a54d36SAndroid Build Coastguard Worker
159*48a54d36SAndroid Build Coastguard Worker result = mDNStrue;
160*48a54d36SAndroid Build Coastguard Worker if (result && strlen(serviceType) > 63) {
161*48a54d36SAndroid Build Coastguard Worker if (printExplanation) {
162*48a54d36SAndroid Build Coastguard Worker fprintf(stderr,
163*48a54d36SAndroid Build Coastguard Worker "%s: Service type is too long (must be 63 characters or less)\n",
164*48a54d36SAndroid Build Coastguard Worker gProgramName);
165*48a54d36SAndroid Build Coastguard Worker }
166*48a54d36SAndroid Build Coastguard Worker result = mDNSfalse;
167*48a54d36SAndroid Build Coastguard Worker }
168*48a54d36SAndroid Build Coastguard Worker if (result && serviceType[0] == 0) {
169*48a54d36SAndroid Build Coastguard Worker if (printExplanation) {
170*48a54d36SAndroid Build Coastguard Worker fprintf(stderr,
171*48a54d36SAndroid Build Coastguard Worker "%s: Service type can't be empty\n",
172*48a54d36SAndroid Build Coastguard Worker gProgramName);
173*48a54d36SAndroid Build Coastguard Worker }
174*48a54d36SAndroid Build Coastguard Worker result = mDNSfalse;
175*48a54d36SAndroid Build Coastguard Worker }
176*48a54d36SAndroid Build Coastguard Worker return result;
177*48a54d36SAndroid Build Coastguard Worker }
178*48a54d36SAndroid Build Coastguard Worker
CheckThatPortNumberIsUsable(long portNumber,mDNSBool printExplanation)179*48a54d36SAndroid Build Coastguard Worker static mDNSBool CheckThatPortNumberIsUsable(long portNumber, mDNSBool printExplanation)
180*48a54d36SAndroid Build Coastguard Worker // Checks that portNumber is a reasonable port number
181*48a54d36SAndroid Build Coastguard Worker // and, if it isn't and printExplanation is true, prints
182*48a54d36SAndroid Build Coastguard Worker // an explanation of why not.
183*48a54d36SAndroid Build Coastguard Worker {
184*48a54d36SAndroid Build Coastguard Worker mDNSBool result;
185*48a54d36SAndroid Build Coastguard Worker
186*48a54d36SAndroid Build Coastguard Worker result = mDNStrue;
187*48a54d36SAndroid Build Coastguard Worker if (result && (portNumber <= 0 || portNumber > 65535)) {
188*48a54d36SAndroid Build Coastguard Worker if (printExplanation) {
189*48a54d36SAndroid Build Coastguard Worker fprintf(stderr,
190*48a54d36SAndroid Build Coastguard Worker "%s: Port number specified by -p must be in range 1..65535\n",
191*48a54d36SAndroid Build Coastguard Worker gProgramName);
192*48a54d36SAndroid Build Coastguard Worker }
193*48a54d36SAndroid Build Coastguard Worker result = mDNSfalse;
194*48a54d36SAndroid Build Coastguard Worker }
195*48a54d36SAndroid Build Coastguard Worker return result;
196*48a54d36SAndroid Build Coastguard Worker }
197*48a54d36SAndroid Build Coastguard Worker
198*48a54d36SAndroid Build Coastguard Worker #if COMPILER_LIKES_PRAGMA_MARK
199*48a54d36SAndroid Build Coastguard Worker #pragma mark ***** Command Line Arguments
200*48a54d36SAndroid Build Coastguard Worker #endif
201*48a54d36SAndroid Build Coastguard Worker
202*48a54d36SAndroid Build Coastguard Worker static const char kDefaultPIDFile[] = "/var/run/mDNSResponder.pid";
203*48a54d36SAndroid Build Coastguard Worker static const char kDefaultServiceType[] = "_afpovertcp._tcp.";
204*48a54d36SAndroid Build Coastguard Worker static const char kDefaultServiceDomain[] = "local.";
205*48a54d36SAndroid Build Coastguard Worker enum {
206*48a54d36SAndroid Build Coastguard Worker kDefaultPortNumber = 548
207*48a54d36SAndroid Build Coastguard Worker };
208*48a54d36SAndroid Build Coastguard Worker
PrintUsage()209*48a54d36SAndroid Build Coastguard Worker static void PrintUsage()
210*48a54d36SAndroid Build Coastguard Worker {
211*48a54d36SAndroid Build Coastguard Worker fprintf(stderr,
212*48a54d36SAndroid Build Coastguard Worker "Usage: %s [-v level ] [-r] [-n name] [-t type] [-d domain] [-p port] [-f file] [-b] [-P pidfile] [-x name=val ...]\n",
213*48a54d36SAndroid Build Coastguard Worker gProgramName);
214*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, " -v verbose mode, level is a number from 0 to 2\n");
215*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, " 0 = no debugging info (default)\n");
216*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, " 1 = standard debugging info\n");
217*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, " 2 = intense debugging info\n");
218*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, " can be cycled kill -USR1\n");
219*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, " -r also bind to port 53 (port 5353 is always bound)\n");
220*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, " -n uses 'name' as the service name (required)\n");
221*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, " -t uses 'type' as the service type (default is '%s')\n", kDefaultServiceType);
222*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, " -d uses 'domain' as the service domain (default is '%s')\n", kDefaultServiceDomain);
223*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, " -p uses 'port' as the port number (default is '%d')\n", kDefaultPortNumber);
224*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, " -f reads a service list from 'file'\n");
225*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, " -b forces daemon (background) mode\n");
226*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, " -P uses 'pidfile' as the PID file\n");
227*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, " (default is '%s')\n", kDefaultPIDFile);
228*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, " only meaningful if -b also specified\n");
229*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, " -x stores name=val in TXT record (default is empty).\n");
230*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, " MUST be the last command-line argument;\n");
231*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, " all subsequent arguments after -x are treated as name=val pairs.\n");
232*48a54d36SAndroid Build Coastguard Worker }
233*48a54d36SAndroid Build Coastguard Worker
234*48a54d36SAndroid Build Coastguard Worker static mDNSBool gAvoidPort53 = mDNStrue;
235*48a54d36SAndroid Build Coastguard Worker static const char *gServiceName = "";
236*48a54d36SAndroid Build Coastguard Worker static const char *gServiceType = kDefaultServiceType;
237*48a54d36SAndroid Build Coastguard Worker static const char *gServiceDomain = kDefaultServiceDomain;
238*48a54d36SAndroid Build Coastguard Worker static mDNSu8 gServiceText[sizeof(RDataBody)];
239*48a54d36SAndroid Build Coastguard Worker static mDNSu16 gServiceTextLen = 0;
240*48a54d36SAndroid Build Coastguard Worker static int gPortNumber = kDefaultPortNumber;
241*48a54d36SAndroid Build Coastguard Worker static const char *gServiceFile = "";
242*48a54d36SAndroid Build Coastguard Worker static mDNSBool gDaemon = mDNSfalse;
243*48a54d36SAndroid Build Coastguard Worker static const char *gPIDFile = kDefaultPIDFile;
244*48a54d36SAndroid Build Coastguard Worker
ParseArguments(int argc,char ** argv)245*48a54d36SAndroid Build Coastguard Worker static void ParseArguments(int argc, char **argv)
246*48a54d36SAndroid Build Coastguard Worker // Parses our command line arguments into the global variables
247*48a54d36SAndroid Build Coastguard Worker // listed above.
248*48a54d36SAndroid Build Coastguard Worker {
249*48a54d36SAndroid Build Coastguard Worker int ch;
250*48a54d36SAndroid Build Coastguard Worker
251*48a54d36SAndroid Build Coastguard Worker // Set gProgramName to the last path component of argv[0]
252*48a54d36SAndroid Build Coastguard Worker
253*48a54d36SAndroid Build Coastguard Worker gProgramName = strrchr(argv[0], '/');
254*48a54d36SAndroid Build Coastguard Worker if (gProgramName == NULL) {
255*48a54d36SAndroid Build Coastguard Worker gProgramName = argv[0];
256*48a54d36SAndroid Build Coastguard Worker } else {
257*48a54d36SAndroid Build Coastguard Worker gProgramName += 1;
258*48a54d36SAndroid Build Coastguard Worker }
259*48a54d36SAndroid Build Coastguard Worker
260*48a54d36SAndroid Build Coastguard Worker // Parse command line options using getopt.
261*48a54d36SAndroid Build Coastguard Worker
262*48a54d36SAndroid Build Coastguard Worker do {
263*48a54d36SAndroid Build Coastguard Worker ch = getopt(argc, argv, "v:rn:t:d:p:f:dP:bx");
264*48a54d36SAndroid Build Coastguard Worker if (ch != -1) {
265*48a54d36SAndroid Build Coastguard Worker switch (ch) {
266*48a54d36SAndroid Build Coastguard Worker case 'v':
267*48a54d36SAndroid Build Coastguard Worker gMDNSPlatformPosixVerboseLevel = atoi(optarg);
268*48a54d36SAndroid Build Coastguard Worker if (gMDNSPlatformPosixVerboseLevel < 0 || gMDNSPlatformPosixVerboseLevel > 2) {
269*48a54d36SAndroid Build Coastguard Worker fprintf(stderr,
270*48a54d36SAndroid Build Coastguard Worker "%s: Verbose mode must be in the range 0..2\n",
271*48a54d36SAndroid Build Coastguard Worker gProgramName);
272*48a54d36SAndroid Build Coastguard Worker exit(1);
273*48a54d36SAndroid Build Coastguard Worker }
274*48a54d36SAndroid Build Coastguard Worker break;
275*48a54d36SAndroid Build Coastguard Worker case 'r':
276*48a54d36SAndroid Build Coastguard Worker gAvoidPort53 = mDNSfalse;
277*48a54d36SAndroid Build Coastguard Worker break;
278*48a54d36SAndroid Build Coastguard Worker case 'n':
279*48a54d36SAndroid Build Coastguard Worker gServiceName = optarg;
280*48a54d36SAndroid Build Coastguard Worker if ( ! CheckThatRichTextNameIsUsable(gServiceName, mDNStrue) ) {
281*48a54d36SAndroid Build Coastguard Worker exit(1);
282*48a54d36SAndroid Build Coastguard Worker }
283*48a54d36SAndroid Build Coastguard Worker break;
284*48a54d36SAndroid Build Coastguard Worker case 't':
285*48a54d36SAndroid Build Coastguard Worker gServiceType = optarg;
286*48a54d36SAndroid Build Coastguard Worker if ( ! CheckThatServiceTypeIsUsable(gServiceType, mDNStrue) ) {
287*48a54d36SAndroid Build Coastguard Worker exit(1);
288*48a54d36SAndroid Build Coastguard Worker }
289*48a54d36SAndroid Build Coastguard Worker break;
290*48a54d36SAndroid Build Coastguard Worker case 'd':
291*48a54d36SAndroid Build Coastguard Worker gServiceDomain = optarg;
292*48a54d36SAndroid Build Coastguard Worker break;
293*48a54d36SAndroid Build Coastguard Worker case 'p':
294*48a54d36SAndroid Build Coastguard Worker gPortNumber = atol(optarg);
295*48a54d36SAndroid Build Coastguard Worker if ( ! CheckThatPortNumberIsUsable(gPortNumber, mDNStrue) ) {
296*48a54d36SAndroid Build Coastguard Worker exit(1);
297*48a54d36SAndroid Build Coastguard Worker }
298*48a54d36SAndroid Build Coastguard Worker break;
299*48a54d36SAndroid Build Coastguard Worker case 'f':
300*48a54d36SAndroid Build Coastguard Worker gServiceFile = optarg;
301*48a54d36SAndroid Build Coastguard Worker break;
302*48a54d36SAndroid Build Coastguard Worker case 'b':
303*48a54d36SAndroid Build Coastguard Worker gDaemon = mDNStrue;
304*48a54d36SAndroid Build Coastguard Worker break;
305*48a54d36SAndroid Build Coastguard Worker case 'P':
306*48a54d36SAndroid Build Coastguard Worker gPIDFile = optarg;
307*48a54d36SAndroid Build Coastguard Worker break;
308*48a54d36SAndroid Build Coastguard Worker case 'x':
309*48a54d36SAndroid Build Coastguard Worker while (optind < argc)
310*48a54d36SAndroid Build Coastguard Worker {
311*48a54d36SAndroid Build Coastguard Worker gServiceText[gServiceTextLen] = strlen(argv[optind]);
312*48a54d36SAndroid Build Coastguard Worker mDNSPlatformMemCopy(gServiceText+gServiceTextLen+1, argv[optind], gServiceText[gServiceTextLen]);
313*48a54d36SAndroid Build Coastguard Worker gServiceTextLen += 1 + gServiceText[gServiceTextLen];
314*48a54d36SAndroid Build Coastguard Worker optind++;
315*48a54d36SAndroid Build Coastguard Worker }
316*48a54d36SAndroid Build Coastguard Worker ch = -1;
317*48a54d36SAndroid Build Coastguard Worker break;
318*48a54d36SAndroid Build Coastguard Worker case '?':
319*48a54d36SAndroid Build Coastguard Worker default:
320*48a54d36SAndroid Build Coastguard Worker PrintUsage();
321*48a54d36SAndroid Build Coastguard Worker exit(1);
322*48a54d36SAndroid Build Coastguard Worker break;
323*48a54d36SAndroid Build Coastguard Worker }
324*48a54d36SAndroid Build Coastguard Worker }
325*48a54d36SAndroid Build Coastguard Worker } while (ch != -1);
326*48a54d36SAndroid Build Coastguard Worker
327*48a54d36SAndroid Build Coastguard Worker // Check for any left over command line arguments.
328*48a54d36SAndroid Build Coastguard Worker
329*48a54d36SAndroid Build Coastguard Worker if (optind != argc) {
330*48a54d36SAndroid Build Coastguard Worker PrintUsage();
331*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "%s: Unexpected argument '%s'\n", gProgramName, argv[optind]);
332*48a54d36SAndroid Build Coastguard Worker exit(1);
333*48a54d36SAndroid Build Coastguard Worker }
334*48a54d36SAndroid Build Coastguard Worker
335*48a54d36SAndroid Build Coastguard Worker // Check for inconsistency between the arguments.
336*48a54d36SAndroid Build Coastguard Worker
337*48a54d36SAndroid Build Coastguard Worker if ( (gServiceName[0] == 0) && (gServiceFile[0] == 0) ) {
338*48a54d36SAndroid Build Coastguard Worker PrintUsage();
339*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "%s: You must specify a service name to register (-n) or a service file (-f).\n", gProgramName);
340*48a54d36SAndroid Build Coastguard Worker exit(1);
341*48a54d36SAndroid Build Coastguard Worker }
342*48a54d36SAndroid Build Coastguard Worker }
343*48a54d36SAndroid Build Coastguard Worker
344*48a54d36SAndroid Build Coastguard Worker #if COMPILER_LIKES_PRAGMA_MARK
345*48a54d36SAndroid Build Coastguard Worker #pragma mark ***** Registration
346*48a54d36SAndroid Build Coastguard Worker #endif
347*48a54d36SAndroid Build Coastguard Worker
348*48a54d36SAndroid Build Coastguard Worker typedef struct PosixService PosixService;
349*48a54d36SAndroid Build Coastguard Worker
350*48a54d36SAndroid Build Coastguard Worker struct PosixService {
351*48a54d36SAndroid Build Coastguard Worker ServiceRecordSet coreServ;
352*48a54d36SAndroid Build Coastguard Worker PosixService *next;
353*48a54d36SAndroid Build Coastguard Worker int serviceID;
354*48a54d36SAndroid Build Coastguard Worker };
355*48a54d36SAndroid Build Coastguard Worker
356*48a54d36SAndroid Build Coastguard Worker static PosixService *gServiceList = NULL;
357*48a54d36SAndroid Build Coastguard Worker
RegistrationCallback(mDNS * const m,ServiceRecordSet * const thisRegistration,mStatus status)358*48a54d36SAndroid Build Coastguard Worker static void RegistrationCallback(mDNS *const m, ServiceRecordSet *const thisRegistration, mStatus status)
359*48a54d36SAndroid Build Coastguard Worker // mDNS core calls this routine to tell us about the status of
360*48a54d36SAndroid Build Coastguard Worker // our registration. The appropriate action to take depends
361*48a54d36SAndroid Build Coastguard Worker // entirely on the value of status.
362*48a54d36SAndroid Build Coastguard Worker {
363*48a54d36SAndroid Build Coastguard Worker switch (status) {
364*48a54d36SAndroid Build Coastguard Worker
365*48a54d36SAndroid Build Coastguard Worker case mStatus_NoError:
366*48a54d36SAndroid Build Coastguard Worker debugf("Callback: %##s Name Registered", thisRegistration->RR_SRV.resrec.name->c);
367*48a54d36SAndroid Build Coastguard Worker // Do nothing; our name was successfully registered. We may
368*48a54d36SAndroid Build Coastguard Worker // get more call backs in the future.
369*48a54d36SAndroid Build Coastguard Worker break;
370*48a54d36SAndroid Build Coastguard Worker
371*48a54d36SAndroid Build Coastguard Worker case mStatus_NameConflict:
372*48a54d36SAndroid Build Coastguard Worker debugf("Callback: %##s Name Conflict", thisRegistration->RR_SRV.resrec.name->c);
373*48a54d36SAndroid Build Coastguard Worker
374*48a54d36SAndroid Build Coastguard Worker // In the event of a conflict, this sample RegistrationCallback
375*48a54d36SAndroid Build Coastguard Worker // just calls mDNS_RenameAndReregisterService to automatically
376*48a54d36SAndroid Build Coastguard Worker // pick a new unique name for the service. For a device such as a
377*48a54d36SAndroid Build Coastguard Worker // printer, this may be appropriate. For a device with a user
378*48a54d36SAndroid Build Coastguard Worker // interface, and a screen, and a keyboard, the appropriate response
379*48a54d36SAndroid Build Coastguard Worker // may be to prompt the user and ask them to choose a new name for
380*48a54d36SAndroid Build Coastguard Worker // the service.
381*48a54d36SAndroid Build Coastguard Worker //
382*48a54d36SAndroid Build Coastguard Worker // Also, what do we do if mDNS_RenameAndReregisterService returns an
383*48a54d36SAndroid Build Coastguard Worker // error. Right now I have no place to send that error to.
384*48a54d36SAndroid Build Coastguard Worker
385*48a54d36SAndroid Build Coastguard Worker status = mDNS_RenameAndReregisterService(m, thisRegistration, mDNSNULL);
386*48a54d36SAndroid Build Coastguard Worker assert(status == mStatus_NoError);
387*48a54d36SAndroid Build Coastguard Worker break;
388*48a54d36SAndroid Build Coastguard Worker
389*48a54d36SAndroid Build Coastguard Worker case mStatus_MemFree:
390*48a54d36SAndroid Build Coastguard Worker debugf("Callback: %##s Memory Free", thisRegistration->RR_SRV.resrec.name->c);
391*48a54d36SAndroid Build Coastguard Worker
392*48a54d36SAndroid Build Coastguard Worker // When debugging is enabled, make sure that thisRegistration
393*48a54d36SAndroid Build Coastguard Worker // is not on our gServiceList.
394*48a54d36SAndroid Build Coastguard Worker
395*48a54d36SAndroid Build Coastguard Worker #if !defined(NDEBUG)
396*48a54d36SAndroid Build Coastguard Worker {
397*48a54d36SAndroid Build Coastguard Worker PosixService *cursor;
398*48a54d36SAndroid Build Coastguard Worker
399*48a54d36SAndroid Build Coastguard Worker cursor = gServiceList;
400*48a54d36SAndroid Build Coastguard Worker while (cursor != NULL) {
401*48a54d36SAndroid Build Coastguard Worker assert(&cursor->coreServ != thisRegistration);
402*48a54d36SAndroid Build Coastguard Worker cursor = cursor->next;
403*48a54d36SAndroid Build Coastguard Worker }
404*48a54d36SAndroid Build Coastguard Worker }
405*48a54d36SAndroid Build Coastguard Worker #endif
406*48a54d36SAndroid Build Coastguard Worker free(thisRegistration);
407*48a54d36SAndroid Build Coastguard Worker break;
408*48a54d36SAndroid Build Coastguard Worker
409*48a54d36SAndroid Build Coastguard Worker default:
410*48a54d36SAndroid Build Coastguard Worker debugf("Callback: %##s Unknown Status %ld", thisRegistration->RR_SRV.resrec.name->c, status);
411*48a54d36SAndroid Build Coastguard Worker break;
412*48a54d36SAndroid Build Coastguard Worker }
413*48a54d36SAndroid Build Coastguard Worker }
414*48a54d36SAndroid Build Coastguard Worker
415*48a54d36SAndroid Build Coastguard Worker static int gServiceID = 0;
416*48a54d36SAndroid Build Coastguard Worker
RegisterOneService(const char * richTextName,const char * serviceType,const char * serviceDomain,const mDNSu8 text[],mDNSu16 textLen,long portNumber)417*48a54d36SAndroid Build Coastguard Worker static mStatus RegisterOneService(const char * richTextName,
418*48a54d36SAndroid Build Coastguard Worker const char * serviceType,
419*48a54d36SAndroid Build Coastguard Worker const char * serviceDomain,
420*48a54d36SAndroid Build Coastguard Worker const mDNSu8 text[],
421*48a54d36SAndroid Build Coastguard Worker mDNSu16 textLen,
422*48a54d36SAndroid Build Coastguard Worker long portNumber)
423*48a54d36SAndroid Build Coastguard Worker {
424*48a54d36SAndroid Build Coastguard Worker mStatus status;
425*48a54d36SAndroid Build Coastguard Worker PosixService * thisServ;
426*48a54d36SAndroid Build Coastguard Worker domainlabel name;
427*48a54d36SAndroid Build Coastguard Worker domainname type;
428*48a54d36SAndroid Build Coastguard Worker domainname domain;
429*48a54d36SAndroid Build Coastguard Worker
430*48a54d36SAndroid Build Coastguard Worker status = mStatus_NoError;
431*48a54d36SAndroid Build Coastguard Worker thisServ = (PosixService *) malloc(sizeof(*thisServ));
432*48a54d36SAndroid Build Coastguard Worker if (thisServ == NULL) {
433*48a54d36SAndroid Build Coastguard Worker status = mStatus_NoMemoryErr;
434*48a54d36SAndroid Build Coastguard Worker }
435*48a54d36SAndroid Build Coastguard Worker if (status == mStatus_NoError) {
436*48a54d36SAndroid Build Coastguard Worker MakeDomainLabelFromLiteralString(&name, richTextName);
437*48a54d36SAndroid Build Coastguard Worker MakeDomainNameFromDNSNameString(&type, serviceType);
438*48a54d36SAndroid Build Coastguard Worker MakeDomainNameFromDNSNameString(&domain, serviceDomain);
439*48a54d36SAndroid Build Coastguard Worker status = mDNS_RegisterService(&mDNSStorage, &thisServ->coreServ,
440*48a54d36SAndroid Build Coastguard Worker &name, &type, &domain, // Name, type, domain
441*48a54d36SAndroid Build Coastguard Worker NULL, mDNSOpaque16fromIntVal(portNumber),
442*48a54d36SAndroid Build Coastguard Worker text, textLen, // TXT data, length
443*48a54d36SAndroid Build Coastguard Worker NULL, 0, // Subtypes
444*48a54d36SAndroid Build Coastguard Worker mDNSInterface_Any, // Interface ID
445*48a54d36SAndroid Build Coastguard Worker RegistrationCallback, thisServ, 0); // Callback, context, flags
446*48a54d36SAndroid Build Coastguard Worker }
447*48a54d36SAndroid Build Coastguard Worker if (status == mStatus_NoError) {
448*48a54d36SAndroid Build Coastguard Worker thisServ->serviceID = gServiceID;
449*48a54d36SAndroid Build Coastguard Worker gServiceID += 1;
450*48a54d36SAndroid Build Coastguard Worker
451*48a54d36SAndroid Build Coastguard Worker thisServ->next = gServiceList;
452*48a54d36SAndroid Build Coastguard Worker gServiceList = thisServ;
453*48a54d36SAndroid Build Coastguard Worker
454*48a54d36SAndroid Build Coastguard Worker if (gMDNSPlatformPosixVerboseLevel > 0) {
455*48a54d36SAndroid Build Coastguard Worker fprintf(stderr,
456*48a54d36SAndroid Build Coastguard Worker "%s: Registered service %d, name \"%s\", type \"%s\", domain \"%s\", port %ld\n",
457*48a54d36SAndroid Build Coastguard Worker gProgramName,
458*48a54d36SAndroid Build Coastguard Worker thisServ->serviceID,
459*48a54d36SAndroid Build Coastguard Worker richTextName,
460*48a54d36SAndroid Build Coastguard Worker serviceType,
461*48a54d36SAndroid Build Coastguard Worker serviceDomain,
462*48a54d36SAndroid Build Coastguard Worker portNumber);
463*48a54d36SAndroid Build Coastguard Worker }
464*48a54d36SAndroid Build Coastguard Worker } else {
465*48a54d36SAndroid Build Coastguard Worker if (thisServ != NULL) {
466*48a54d36SAndroid Build Coastguard Worker free(thisServ);
467*48a54d36SAndroid Build Coastguard Worker }
468*48a54d36SAndroid Build Coastguard Worker }
469*48a54d36SAndroid Build Coastguard Worker return status;
470*48a54d36SAndroid Build Coastguard Worker }
471*48a54d36SAndroid Build Coastguard Worker
ReadALine(char * buf,size_t bufSize,FILE * fp,mDNSBool skipBlankLines)472*48a54d36SAndroid Build Coastguard Worker static mDNSBool ReadALine(char *buf, size_t bufSize, FILE *fp, mDNSBool skipBlankLines)
473*48a54d36SAndroid Build Coastguard Worker {
474*48a54d36SAndroid Build Coastguard Worker size_t len;
475*48a54d36SAndroid Build Coastguard Worker mDNSBool readNextLine;
476*48a54d36SAndroid Build Coastguard Worker
477*48a54d36SAndroid Build Coastguard Worker do {
478*48a54d36SAndroid Build Coastguard Worker readNextLine = mDNSfalse;
479*48a54d36SAndroid Build Coastguard Worker
480*48a54d36SAndroid Build Coastguard Worker if (fgets(buf, bufSize, fp) == NULL)
481*48a54d36SAndroid Build Coastguard Worker return mDNSfalse; // encountered EOF or an error condition
482*48a54d36SAndroid Build Coastguard Worker
483*48a54d36SAndroid Build Coastguard Worker // These first characters indicate a blank line.
484*48a54d36SAndroid Build Coastguard Worker if (buf[0] == ' ' || buf[0] == '\t' || buf[0] == '\r' || buf[0] == '\n') {
485*48a54d36SAndroid Build Coastguard Worker if (!skipBlankLines)
486*48a54d36SAndroid Build Coastguard Worker return mDNSfalse;
487*48a54d36SAndroid Build Coastguard Worker readNextLine = mDNStrue;
488*48a54d36SAndroid Build Coastguard Worker }
489*48a54d36SAndroid Build Coastguard Worker // always skip comment lines
490*48a54d36SAndroid Build Coastguard Worker if (buf[0] == '#')
491*48a54d36SAndroid Build Coastguard Worker readNextLine = mDNStrue;
492*48a54d36SAndroid Build Coastguard Worker
493*48a54d36SAndroid Build Coastguard Worker } while (readNextLine);
494*48a54d36SAndroid Build Coastguard Worker
495*48a54d36SAndroid Build Coastguard Worker len = strlen( buf);
496*48a54d36SAndroid Build Coastguard Worker if ( buf[len - 1] == '\r' || buf[len - 1] == '\n')
497*48a54d36SAndroid Build Coastguard Worker buf[len - 1] = '\0';
498*48a54d36SAndroid Build Coastguard Worker
499*48a54d36SAndroid Build Coastguard Worker return mDNStrue;
500*48a54d36SAndroid Build Coastguard Worker }
501*48a54d36SAndroid Build Coastguard Worker
RegisterServicesInFile(const char * filePath)502*48a54d36SAndroid Build Coastguard Worker static mStatus RegisterServicesInFile(const char *filePath)
503*48a54d36SAndroid Build Coastguard Worker {
504*48a54d36SAndroid Build Coastguard Worker mStatus status = mStatus_NoError;
505*48a54d36SAndroid Build Coastguard Worker FILE * fp = fopen(filePath, "r");
506*48a54d36SAndroid Build Coastguard Worker
507*48a54d36SAndroid Build Coastguard Worker if (fp == NULL) {
508*48a54d36SAndroid Build Coastguard Worker return mStatus_UnknownErr;
509*48a54d36SAndroid Build Coastguard Worker }
510*48a54d36SAndroid Build Coastguard Worker
511*48a54d36SAndroid Build Coastguard Worker if (gMDNSPlatformPosixVerboseLevel > 1)
512*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "Parsing %s for services\n", filePath);
513*48a54d36SAndroid Build Coastguard Worker
514*48a54d36SAndroid Build Coastguard Worker do {
515*48a54d36SAndroid Build Coastguard Worker char nameBuf[256];
516*48a54d36SAndroid Build Coastguard Worker char * name = nameBuf;
517*48a54d36SAndroid Build Coastguard Worker char type[256];
518*48a54d36SAndroid Build Coastguard Worker const char *dom = kDefaultServiceDomain;
519*48a54d36SAndroid Build Coastguard Worker char rawText[1024];
520*48a54d36SAndroid Build Coastguard Worker mDNSu8 text[sizeof(RDataBody)];
521*48a54d36SAndroid Build Coastguard Worker unsigned int textLen = 0;
522*48a54d36SAndroid Build Coastguard Worker char port[256];
523*48a54d36SAndroid Build Coastguard Worker char *p;
524*48a54d36SAndroid Build Coastguard Worker
525*48a54d36SAndroid Build Coastguard Worker // Read the service name, type, port, and optional text record fields.
526*48a54d36SAndroid Build Coastguard Worker // Skip blank lines while looking for the next service name.
527*48a54d36SAndroid Build Coastguard Worker if (! ReadALine(name, sizeof(nameBuf), fp, mDNStrue))
528*48a54d36SAndroid Build Coastguard Worker break;
529*48a54d36SAndroid Build Coastguard Worker
530*48a54d36SAndroid Build Coastguard Worker // Special case that allows service name to begin with a '#'
531*48a54d36SAndroid Build Coastguard Worker // character by escaping it with a '\' to distiguish it from
532*48a54d36SAndroid Build Coastguard Worker // a comment line. Remove the leading '\' here before
533*48a54d36SAndroid Build Coastguard Worker // registering the service.
534*48a54d36SAndroid Build Coastguard Worker if (name[0] == '\\' && name[1] == '#')
535*48a54d36SAndroid Build Coastguard Worker name++;
536*48a54d36SAndroid Build Coastguard Worker
537*48a54d36SAndroid Build Coastguard Worker if (gMDNSPlatformPosixVerboseLevel > 1)
538*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "Service name: \"%s\"\n", name);
539*48a54d36SAndroid Build Coastguard Worker
540*48a54d36SAndroid Build Coastguard Worker // Don't skip blank lines in calls to ReadAline() after finding the
541*48a54d36SAndroid Build Coastguard Worker // service name since the next blank line indicates the end
542*48a54d36SAndroid Build Coastguard Worker // of this service record.
543*48a54d36SAndroid Build Coastguard Worker if (! ReadALine(type, sizeof(type), fp, mDNSfalse))
544*48a54d36SAndroid Build Coastguard Worker break;
545*48a54d36SAndroid Build Coastguard Worker
546*48a54d36SAndroid Build Coastguard Worker // see if a domain name is specified
547*48a54d36SAndroid Build Coastguard Worker p = type;
548*48a54d36SAndroid Build Coastguard Worker while (*p && *p != ' ' && *p != '\t') p++;
549*48a54d36SAndroid Build Coastguard Worker if (*p) {
550*48a54d36SAndroid Build Coastguard Worker *p = 0; // NULL terminate the <type>.<protocol> string
551*48a54d36SAndroid Build Coastguard Worker // skip any leading whitespace before domain name
552*48a54d36SAndroid Build Coastguard Worker p++;
553*48a54d36SAndroid Build Coastguard Worker while (*p && (*p == ' ' || *p == '\t')) p++;
554*48a54d36SAndroid Build Coastguard Worker if (*p)
555*48a54d36SAndroid Build Coastguard Worker dom = p;
556*48a54d36SAndroid Build Coastguard Worker }
557*48a54d36SAndroid Build Coastguard Worker if (gMDNSPlatformPosixVerboseLevel > 1) {
558*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "Service type: \"%s\"\n", type);
559*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "Service domain: \"%s\"\n", dom);
560*48a54d36SAndroid Build Coastguard Worker }
561*48a54d36SAndroid Build Coastguard Worker
562*48a54d36SAndroid Build Coastguard Worker if (! ReadALine(port, sizeof(port), fp, mDNSfalse))
563*48a54d36SAndroid Build Coastguard Worker break;
564*48a54d36SAndroid Build Coastguard Worker if (gMDNSPlatformPosixVerboseLevel > 1)
565*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "Service port: %s\n", port);
566*48a54d36SAndroid Build Coastguard Worker
567*48a54d36SAndroid Build Coastguard Worker if ( ! CheckThatRichTextNameIsUsable(name, mDNStrue)
568*48a54d36SAndroid Build Coastguard Worker || ! CheckThatServiceTypeIsUsable(type, mDNStrue)
569*48a54d36SAndroid Build Coastguard Worker || ! CheckThatPortNumberIsUsable(atol(port), mDNStrue))
570*48a54d36SAndroid Build Coastguard Worker break;
571*48a54d36SAndroid Build Coastguard Worker
572*48a54d36SAndroid Build Coastguard Worker // read the TXT record fields
573*48a54d36SAndroid Build Coastguard Worker while (1) {
574*48a54d36SAndroid Build Coastguard Worker int len;
575*48a54d36SAndroid Build Coastguard Worker if (!ReadALine(rawText, sizeof(rawText), fp, mDNSfalse)) break;
576*48a54d36SAndroid Build Coastguard Worker if (gMDNSPlatformPosixVerboseLevel > 1)
577*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "Text string: \"%s\"\n", rawText);
578*48a54d36SAndroid Build Coastguard Worker len = strlen(rawText);
579*48a54d36SAndroid Build Coastguard Worker if (len <= 255)
580*48a54d36SAndroid Build Coastguard Worker {
581*48a54d36SAndroid Build Coastguard Worker unsigned int newlen = textLen + 1 + len;
582*48a54d36SAndroid Build Coastguard Worker if (len == 0 || newlen >= sizeof(text)) break;
583*48a54d36SAndroid Build Coastguard Worker text[textLen] = len;
584*48a54d36SAndroid Build Coastguard Worker mDNSPlatformMemCopy(text + textLen + 1, rawText, len);
585*48a54d36SAndroid Build Coastguard Worker textLen = newlen;
586*48a54d36SAndroid Build Coastguard Worker }
587*48a54d36SAndroid Build Coastguard Worker else
588*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "%s: TXT attribute too long for name = %s, type = %s, port = %s\n",
589*48a54d36SAndroid Build Coastguard Worker gProgramName, name, type, port);
590*48a54d36SAndroid Build Coastguard Worker }
591*48a54d36SAndroid Build Coastguard Worker
592*48a54d36SAndroid Build Coastguard Worker status = RegisterOneService(name, type, dom, text, textLen, atol(port));
593*48a54d36SAndroid Build Coastguard Worker if (status != mStatus_NoError) {
594*48a54d36SAndroid Build Coastguard Worker // print error, but try to read and register other services in the file
595*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "%s: Failed to register service, name \"%s\", type \"%s\", domain \"%s\", port %s\n",
596*48a54d36SAndroid Build Coastguard Worker gProgramName, name, type, dom, port);
597*48a54d36SAndroid Build Coastguard Worker }
598*48a54d36SAndroid Build Coastguard Worker
599*48a54d36SAndroid Build Coastguard Worker } while (!feof(fp));
600*48a54d36SAndroid Build Coastguard Worker
601*48a54d36SAndroid Build Coastguard Worker if (!feof(fp)) {
602*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "%s: Error reading service file %s\n", gProgramName, filePath);
603*48a54d36SAndroid Build Coastguard Worker status = mStatus_UnknownErr;
604*48a54d36SAndroid Build Coastguard Worker }
605*48a54d36SAndroid Build Coastguard Worker
606*48a54d36SAndroid Build Coastguard Worker {
607*48a54d36SAndroid Build Coastguard Worker // __ANDROID__ : replaced assert(fclose(..))
608*48a54d36SAndroid Build Coastguard Worker int fp_closed = fclose(fp);
609*48a54d36SAndroid Build Coastguard Worker assert(0 == fp_closed);
610*48a54d36SAndroid Build Coastguard Worker }
611*48a54d36SAndroid Build Coastguard Worker
612*48a54d36SAndroid Build Coastguard Worker return status;
613*48a54d36SAndroid Build Coastguard Worker }
614*48a54d36SAndroid Build Coastguard Worker
RegisterOurServices(void)615*48a54d36SAndroid Build Coastguard Worker static mStatus RegisterOurServices(void)
616*48a54d36SAndroid Build Coastguard Worker {
617*48a54d36SAndroid Build Coastguard Worker mStatus status;
618*48a54d36SAndroid Build Coastguard Worker
619*48a54d36SAndroid Build Coastguard Worker status = mStatus_NoError;
620*48a54d36SAndroid Build Coastguard Worker if (gServiceName[0] != 0) {
621*48a54d36SAndroid Build Coastguard Worker status = RegisterOneService(gServiceName,
622*48a54d36SAndroid Build Coastguard Worker gServiceType,
623*48a54d36SAndroid Build Coastguard Worker gServiceDomain,
624*48a54d36SAndroid Build Coastguard Worker gServiceText, gServiceTextLen,
625*48a54d36SAndroid Build Coastguard Worker gPortNumber);
626*48a54d36SAndroid Build Coastguard Worker }
627*48a54d36SAndroid Build Coastguard Worker if (status == mStatus_NoError && gServiceFile[0] != 0) {
628*48a54d36SAndroid Build Coastguard Worker status = RegisterServicesInFile(gServiceFile);
629*48a54d36SAndroid Build Coastguard Worker }
630*48a54d36SAndroid Build Coastguard Worker return status;
631*48a54d36SAndroid Build Coastguard Worker }
632*48a54d36SAndroid Build Coastguard Worker
DeregisterOurServices(void)633*48a54d36SAndroid Build Coastguard Worker static void DeregisterOurServices(void)
634*48a54d36SAndroid Build Coastguard Worker {
635*48a54d36SAndroid Build Coastguard Worker PosixService *thisServ;
636*48a54d36SAndroid Build Coastguard Worker int thisServID;
637*48a54d36SAndroid Build Coastguard Worker
638*48a54d36SAndroid Build Coastguard Worker while (gServiceList != NULL) {
639*48a54d36SAndroid Build Coastguard Worker thisServ = gServiceList;
640*48a54d36SAndroid Build Coastguard Worker gServiceList = thisServ->next;
641*48a54d36SAndroid Build Coastguard Worker
642*48a54d36SAndroid Build Coastguard Worker thisServID = thisServ->serviceID;
643*48a54d36SAndroid Build Coastguard Worker
644*48a54d36SAndroid Build Coastguard Worker mDNS_DeregisterService(&mDNSStorage, &thisServ->coreServ);
645*48a54d36SAndroid Build Coastguard Worker
646*48a54d36SAndroid Build Coastguard Worker if (gMDNSPlatformPosixVerboseLevel > 0) {
647*48a54d36SAndroid Build Coastguard Worker fprintf(stderr,
648*48a54d36SAndroid Build Coastguard Worker "%s: Deregistered service %d\n",
649*48a54d36SAndroid Build Coastguard Worker gProgramName,
650*48a54d36SAndroid Build Coastguard Worker thisServ->serviceID);
651*48a54d36SAndroid Build Coastguard Worker }
652*48a54d36SAndroid Build Coastguard Worker }
653*48a54d36SAndroid Build Coastguard Worker }
654*48a54d36SAndroid Build Coastguard Worker
655*48a54d36SAndroid Build Coastguard Worker #if COMPILER_LIKES_PRAGMA_MARK
656*48a54d36SAndroid Build Coastguard Worker #pragma mark **** Main
657*48a54d36SAndroid Build Coastguard Worker #endif
658*48a54d36SAndroid Build Coastguard Worker
main(int argc,char ** argv)659*48a54d36SAndroid Build Coastguard Worker int main(int argc, char **argv)
660*48a54d36SAndroid Build Coastguard Worker {
661*48a54d36SAndroid Build Coastguard Worker mStatus status;
662*48a54d36SAndroid Build Coastguard Worker int result;
663*48a54d36SAndroid Build Coastguard Worker
664*48a54d36SAndroid Build Coastguard Worker // Parse our command line arguments. This won't come back if there's an error.
665*48a54d36SAndroid Build Coastguard Worker
666*48a54d36SAndroid Build Coastguard Worker ParseArguments(argc, argv);
667*48a54d36SAndroid Build Coastguard Worker
668*48a54d36SAndroid Build Coastguard Worker // If we're told to run as a daemon, then do that straight away.
669*48a54d36SAndroid Build Coastguard Worker // Note that we don't treat the inability to create our PID
670*48a54d36SAndroid Build Coastguard Worker // file as an error. Also note that we assign getpid to a long
671*48a54d36SAndroid Build Coastguard Worker // because printf has no format specified for pid_t.
672*48a54d36SAndroid Build Coastguard Worker
673*48a54d36SAndroid Build Coastguard Worker if (gDaemon) {
674*48a54d36SAndroid Build Coastguard Worker int result;
675*48a54d36SAndroid Build Coastguard Worker if (gMDNSPlatformPosixVerboseLevel > 0) {
676*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "%s: Starting in daemon mode\n", gProgramName);
677*48a54d36SAndroid Build Coastguard Worker }
678*48a54d36SAndroid Build Coastguard Worker result = daemon(0,0);
679*48a54d36SAndroid Build Coastguard Worker if (result == 0) {
680*48a54d36SAndroid Build Coastguard Worker FILE *fp;
681*48a54d36SAndroid Build Coastguard Worker int junk;
682*48a54d36SAndroid Build Coastguard Worker
683*48a54d36SAndroid Build Coastguard Worker fp = fopen(gPIDFile, "w");
684*48a54d36SAndroid Build Coastguard Worker if (fp != NULL) {
685*48a54d36SAndroid Build Coastguard Worker fprintf(fp, "%ld\n", (long) getpid());
686*48a54d36SAndroid Build Coastguard Worker junk = fclose(fp);
687*48a54d36SAndroid Build Coastguard Worker assert(junk == 0);
688*48a54d36SAndroid Build Coastguard Worker }
689*48a54d36SAndroid Build Coastguard Worker } else {
690*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "%s: Could not run as daemon - exiting\n", gProgramName);
691*48a54d36SAndroid Build Coastguard Worker exit(result);
692*48a54d36SAndroid Build Coastguard Worker }
693*48a54d36SAndroid Build Coastguard Worker } else {
694*48a54d36SAndroid Build Coastguard Worker if (gMDNSPlatformPosixVerboseLevel > 0) {
695*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "%s: Starting in foreground mode, PID %ld\n", gProgramName, (long) getpid());
696*48a54d36SAndroid Build Coastguard Worker }
697*48a54d36SAndroid Build Coastguard Worker }
698*48a54d36SAndroid Build Coastguard Worker
699*48a54d36SAndroid Build Coastguard Worker status = mDNS_Init(&mDNSStorage, &PlatformStorage,
700*48a54d36SAndroid Build Coastguard Worker mDNS_Init_NoCache, mDNS_Init_ZeroCacheSize,
701*48a54d36SAndroid Build Coastguard Worker mDNS_Init_AdvertiseLocalAddresses,
702*48a54d36SAndroid Build Coastguard Worker mDNS_Init_NoInitCallback, mDNS_Init_NoInitCallbackContext);
703*48a54d36SAndroid Build Coastguard Worker if (status != mStatus_NoError) return(2);
704*48a54d36SAndroid Build Coastguard Worker
705*48a54d36SAndroid Build Coastguard Worker status = RegisterOurServices();
706*48a54d36SAndroid Build Coastguard Worker if (status != mStatus_NoError) return(2);
707*48a54d36SAndroid Build Coastguard Worker
708*48a54d36SAndroid Build Coastguard Worker signal(SIGHUP, HandleSigHup); // SIGHUP has to be sent by kill -HUP <pid>
709*48a54d36SAndroid Build Coastguard Worker signal(SIGINT, HandleSigInt); // SIGINT is what you get for a Ctrl-C
710*48a54d36SAndroid Build Coastguard Worker signal(SIGQUIT, HandleSigQuit); // SIGQUIT is what you get for a Ctrl-\ (indeed)
711*48a54d36SAndroid Build Coastguard Worker signal(SIGUSR1, HandleSigUsr1); // SIGUSR1 has to be sent by kill -USR1 <pid>
712*48a54d36SAndroid Build Coastguard Worker
713*48a54d36SAndroid Build Coastguard Worker while (!gStopNow)
714*48a54d36SAndroid Build Coastguard Worker {
715*48a54d36SAndroid Build Coastguard Worker int nfds = 0;
716*48a54d36SAndroid Build Coastguard Worker fd_set readfds;
717*48a54d36SAndroid Build Coastguard Worker struct timeval timeout;
718*48a54d36SAndroid Build Coastguard Worker int result;
719*48a54d36SAndroid Build Coastguard Worker
720*48a54d36SAndroid Build Coastguard Worker // 1. Set up the fd_set as usual here.
721*48a54d36SAndroid Build Coastguard Worker // This example client has no file descriptors of its own,
722*48a54d36SAndroid Build Coastguard Worker // but a real application would call FD_SET to add them to the set here
723*48a54d36SAndroid Build Coastguard Worker FD_ZERO(&readfds);
724*48a54d36SAndroid Build Coastguard Worker
725*48a54d36SAndroid Build Coastguard Worker // 2. Set up the timeout.
726*48a54d36SAndroid Build Coastguard Worker // This example client has no other work it needs to be doing,
727*48a54d36SAndroid Build Coastguard Worker // so we set an effectively infinite timeout
728*48a54d36SAndroid Build Coastguard Worker timeout.tv_sec = 0x3FFFFFFF;
729*48a54d36SAndroid Build Coastguard Worker timeout.tv_usec = 0;
730*48a54d36SAndroid Build Coastguard Worker
731*48a54d36SAndroid Build Coastguard Worker // 3. Give the mDNSPosix layer a chance to add its information to the fd_set and timeout
732*48a54d36SAndroid Build Coastguard Worker mDNSPosixGetFDSet(&mDNSStorage, &nfds, &readfds, &timeout);
733*48a54d36SAndroid Build Coastguard Worker
734*48a54d36SAndroid Build Coastguard Worker // 4. Call select as normal
735*48a54d36SAndroid Build Coastguard Worker verbosedebugf("select(%d, %d.%06d)", nfds, timeout.tv_sec, timeout.tv_usec);
736*48a54d36SAndroid Build Coastguard Worker result = select(nfds, &readfds, NULL, NULL, &timeout);
737*48a54d36SAndroid Build Coastguard Worker
738*48a54d36SAndroid Build Coastguard Worker if (result < 0)
739*48a54d36SAndroid Build Coastguard Worker {
740*48a54d36SAndroid Build Coastguard Worker verbosedebugf("select() returned %d errno %d", result, errno);
741*48a54d36SAndroid Build Coastguard Worker if (errno != EINTR) gStopNow = mDNStrue;
742*48a54d36SAndroid Build Coastguard Worker else
743*48a54d36SAndroid Build Coastguard Worker {
744*48a54d36SAndroid Build Coastguard Worker if (gReceivedSigUsr1)
745*48a54d36SAndroid Build Coastguard Worker {
746*48a54d36SAndroid Build Coastguard Worker gReceivedSigUsr1 = mDNSfalse;
747*48a54d36SAndroid Build Coastguard Worker gMDNSPlatformPosixVerboseLevel += 1;
748*48a54d36SAndroid Build Coastguard Worker if (gMDNSPlatformPosixVerboseLevel > 2)
749*48a54d36SAndroid Build Coastguard Worker gMDNSPlatformPosixVerboseLevel = 0;
750*48a54d36SAndroid Build Coastguard Worker if ( gMDNSPlatformPosixVerboseLevel > 0 )
751*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "\nVerbose level %d\n", gMDNSPlatformPosixVerboseLevel);
752*48a54d36SAndroid Build Coastguard Worker }
753*48a54d36SAndroid Build Coastguard Worker if (gReceivedSigHup)
754*48a54d36SAndroid Build Coastguard Worker {
755*48a54d36SAndroid Build Coastguard Worker if (gMDNSPlatformPosixVerboseLevel > 0)
756*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "\nSIGHUP\n");
757*48a54d36SAndroid Build Coastguard Worker gReceivedSigHup = mDNSfalse;
758*48a54d36SAndroid Build Coastguard Worker DeregisterOurServices();
759*48a54d36SAndroid Build Coastguard Worker status = mDNSPlatformPosixRefreshInterfaceList(&mDNSStorage);
760*48a54d36SAndroid Build Coastguard Worker if (status != mStatus_NoError) break;
761*48a54d36SAndroid Build Coastguard Worker status = RegisterOurServices();
762*48a54d36SAndroid Build Coastguard Worker if (status != mStatus_NoError) break;
763*48a54d36SAndroid Build Coastguard Worker }
764*48a54d36SAndroid Build Coastguard Worker }
765*48a54d36SAndroid Build Coastguard Worker }
766*48a54d36SAndroid Build Coastguard Worker else
767*48a54d36SAndroid Build Coastguard Worker {
768*48a54d36SAndroid Build Coastguard Worker // 5. Call mDNSPosixProcessFDSet to let the mDNSPosix layer do its work
769*48a54d36SAndroid Build Coastguard Worker mDNSPosixProcessFDSet(&mDNSStorage, &readfds);
770*48a54d36SAndroid Build Coastguard Worker
771*48a54d36SAndroid Build Coastguard Worker // 6. This example client has no other work it needs to be doing,
772*48a54d36SAndroid Build Coastguard Worker // but a real client would do its work here
773*48a54d36SAndroid Build Coastguard Worker // ... (do work) ...
774*48a54d36SAndroid Build Coastguard Worker }
775*48a54d36SAndroid Build Coastguard Worker }
776*48a54d36SAndroid Build Coastguard Worker
777*48a54d36SAndroid Build Coastguard Worker debugf("Exiting");
778*48a54d36SAndroid Build Coastguard Worker
779*48a54d36SAndroid Build Coastguard Worker DeregisterOurServices();
780*48a54d36SAndroid Build Coastguard Worker mDNS_Close(&mDNSStorage);
781*48a54d36SAndroid Build Coastguard Worker
782*48a54d36SAndroid Build Coastguard Worker if (status == mStatus_NoError) {
783*48a54d36SAndroid Build Coastguard Worker result = 0;
784*48a54d36SAndroid Build Coastguard Worker } else {
785*48a54d36SAndroid Build Coastguard Worker result = 2;
786*48a54d36SAndroid Build Coastguard Worker }
787*48a54d36SAndroid Build Coastguard Worker if ( (result != 0) || (gMDNSPlatformPosixVerboseLevel > 0) ) {
788*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "%s: Finished with status %d, result %d\n", gProgramName, (int)status, result);
789*48a54d36SAndroid Build Coastguard Worker }
790*48a54d36SAndroid Build Coastguard Worker
791*48a54d36SAndroid Build Coastguard Worker return result;
792*48a54d36SAndroid Build Coastguard Worker }
793