xref: /aosp_15_r20/external/mdnsresponder/mDNSPosix/Responder.c (revision 48a54d368dc4fa860885eef7b70b6c53499e7c25)
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