147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/* -*- Mode: C; tab-width: 4 -*- 247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * 347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved. 447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * 547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * Licensed under the Apache License, Version 2.0 (the "License"); 647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * you may not use this file except in compliance with the License. 747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * You may obtain a copy of the License at 847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * 947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * http://www.apache.org/licenses/LICENSE-2.0 1047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * 1147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * Unless required by applicable law or agreed to in writing, software 1247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * distributed under the License is distributed on an "AS IS" BASIS, 1347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * See the License for the specific language governing permissions and 1547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * limitations under the License. 1647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */ 1747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 1847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if __APPLE__ 1947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// In Mac OS X 10.5 and later trying to use the daemon function gives a “‘daemon’ is deprecated” 2047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// error, which prevents compilation because we build with "-Werror". 2147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Since this is supposed to be portable cross-platform code, we don't care that daemon is 2247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// deprecated on Mac OS X 10.5, so we use this preprocessor trick to eliminate the error message. 2347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#define daemon yes_we_know_that_daemon_is_deprecated_in_os_x_10_5_thankyou 2447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif 2547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 2647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <assert.h> 2747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <stdio.h> // For printf() 2847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <stdlib.h> // For exit() etc. 2947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <string.h> // For strlen() etc. 3047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <unistd.h> // For select() 3147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <errno.h> // For errno, EINTR 3247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <signal.h> 3347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <fcntl.h> 3447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 3547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if __APPLE__ 3647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#undef daemon 3747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltextern int daemon(int, int); 3847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif 3947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 4047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include "mDNSEmbeddedAPI.h"// Defines the interface to the client layer above 4147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include "mDNSPosix.h" // Defines the specific types needed to run mDNS on this platform 4247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include "mDNSUNP.h" // For daemon() 4347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 4447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if COMPILER_LIKES_PRAGMA_MARK 4547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#pragma mark ***** Globals 4647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif 4747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 4847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic mDNS mDNSStorage; // mDNS core uses this to store its globals 4947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic mDNS_PlatformSupport PlatformStorage; // Stores this platform's globals 5047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 5147e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport const char ProgramName[] = "mDNSResponderPosix"; 5247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 5347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic const char *gProgramName = ProgramName; 5447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 5547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if COMPILER_LIKES_PRAGMA_MARK 5647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#pragma mark ***** Signals 5747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif 5847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 5947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic volatile mDNSBool gReceivedSigUsr1; 6047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic volatile mDNSBool gReceivedSigHup; 6147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic volatile mDNSBool gStopNow; 6247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 6347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// We support 4 signals. 6447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// 6547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// o SIGUSR1 toggles verbose mode on and off in debug builds 6647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// o SIGHUP triggers the program to re-read its preferences. 6747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// o SIGINT causes an orderly shutdown of the program. 6847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// o SIGQUIT causes a somewhat orderly shutdown (direct but dangerous) 6947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// o SIGKILL kills us dead (easy to implement :-) 7047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// 7147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// There are fatal race conditions in our signal handling, but there's not much 7247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// we can do about them while remaining within the Posix space. Specifically, 7347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// if a signal arrives after we test the globals its sets but before we call 7447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// select, the signal will be dropped. The user will have to send the signal 7547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// again. Unfortunately, Posix does not have a "sigselect" to atomically 7647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// modify the signal mask and start a select. 7747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 7847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic void HandleSigUsr1(int sigraised) 7947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // If we get a SIGUSR1 we toggle the state of the 8047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // verbose mode. 8147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{ 8247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt assert(sigraised == SIGUSR1); 8347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gReceivedSigUsr1 = mDNStrue; 8447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt} 8547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 8647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic void HandleSigHup(int sigraised) 8747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // A handler for SIGHUP that causes us to break out of the 8847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // main event loop when the user kill 1's us. This has the 8947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // effect of triggered the main loop to deregister the 9047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // current services and re-read the preferences. 9147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{ 9247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt assert(sigraised == SIGHUP); 9347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gReceivedSigHup = mDNStrue; 9447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt} 9547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 9647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic void HandleSigInt(int sigraised) 9747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // A handler for SIGINT that causes us to break out of the 9847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // main event loop when the user types ^C. This has the 9947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // effect of quitting the program. 10047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{ 10147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt assert(sigraised == SIGINT); 10247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 10347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (gMDNSPlatformPosixVerboseLevel > 0) { 10447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, "\nSIGINT\n"); 10547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 10647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gStopNow = mDNStrue; 10747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt} 10847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 10947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic void HandleSigQuit(int sigraised) 11047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // If we get a SIGQUIT the user is desperate and we 11147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // just call mDNS_Close directly. This is definitely 11247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // not safe (because it could reenter mDNS), but 11347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // we presume that the user has already tried the safe 11447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // alternatives. 11547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{ 11647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt assert(sigraised == SIGQUIT); 11747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 11847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (gMDNSPlatformPosixVerboseLevel > 0) { 11947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, "\nSIGQUIT\n"); 12047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 12147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNS_Close(&mDNSStorage); 12247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt exit(0); 12347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt} 12447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 12547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if COMPILER_LIKES_PRAGMA_MARK 12647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#pragma mark ***** Parameter Checking 12747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif 12847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 12947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic mDNSBool CheckThatRichTextNameIsUsable(const char *richTextName, mDNSBool printExplanation) 13047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Checks that richTextName is reasonable 13147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // label and, if it isn't and printExplanation is true, prints 13247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // an explanation of why not. 13347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{ 13447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSBool result = mDNStrue; 13547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (result && strlen(richTextName) > 63) { 13647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (printExplanation) { 13747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, 13847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt "%s: Service name is too long (must be 63 characters or less)\n", 13947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gProgramName); 14047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 14147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt result = mDNSfalse; 14247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 14347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (result && richTextName[0] == 0) { 14447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (printExplanation) { 14547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, "%s: Service name can't be empty\n", gProgramName); 14647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 14747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt result = mDNSfalse; 14847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 14947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return result; 15047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt} 15147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 15247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic mDNSBool CheckThatServiceTypeIsUsable(const char *serviceType, mDNSBool printExplanation) 15347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Checks that serviceType is a reasonable service type 15447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // label and, if it isn't and printExplanation is true, prints 15547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // an explanation of why not. 15647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{ 15747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSBool result; 15847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 15947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt result = mDNStrue; 16047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (result && strlen(serviceType) > 63) { 16147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (printExplanation) { 16247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, 16347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt "%s: Service type is too long (must be 63 characters or less)\n", 16447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gProgramName); 16547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 16647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt result = mDNSfalse; 16747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 16847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (result && serviceType[0] == 0) { 16947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (printExplanation) { 17047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, 17147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt "%s: Service type can't be empty\n", 17247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gProgramName); 17347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 17447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt result = mDNSfalse; 17547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 17647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return result; 17747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt} 17847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 17947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic mDNSBool CheckThatPortNumberIsUsable(long portNumber, mDNSBool printExplanation) 18047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Checks that portNumber is a reasonable port number 18147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // and, if it isn't and printExplanation is true, prints 18247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // an explanation of why not. 18347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{ 18447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSBool result; 18547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 18647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt result = mDNStrue; 18747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (result && (portNumber <= 0 || portNumber > 65535)) { 18847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (printExplanation) { 18947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, 19047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt "%s: Port number specified by -p must be in range 1..65535\n", 19147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gProgramName); 19247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 19347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt result = mDNSfalse; 19447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 19547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return result; 19647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt} 19747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 19847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if COMPILER_LIKES_PRAGMA_MARK 19947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#pragma mark ***** Command Line Arguments 20047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif 20147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 20247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic const char kDefaultPIDFile[] = "/var/run/mDNSResponder.pid"; 20347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic const char kDefaultServiceType[] = "_afpovertcp._tcp."; 20447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic const char kDefaultServiceDomain[] = "local."; 20547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltenum { 20647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt kDefaultPortNumber = 548 20747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}; 20847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 20947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic void PrintUsage() 21047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{ 21147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, 21247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt "Usage: %s [-v level ] [-r] [-n name] [-t type] [-d domain] [-p port] [-f file] [-b] [-P pidfile] [-x name=val ...]\n", 21347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gProgramName); 21447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, " -v verbose mode, level is a number from 0 to 2\n"); 21547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, " 0 = no debugging info (default)\n"); 21647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, " 1 = standard debugging info\n"); 21747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, " 2 = intense debugging info\n"); 21847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, " can be cycled kill -USR1\n"); 21947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, " -r also bind to port 53 (port 5353 is always bound)\n"); 22047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, " -n uses 'name' as the service name (required)\n"); 22147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, " -t uses 'type' as the service type (default is '%s')\n", kDefaultServiceType); 22247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, " -d uses 'domain' as the service domain (default is '%s')\n", kDefaultServiceDomain); 22347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, " -p uses 'port' as the port number (default is '%d')\n", kDefaultPortNumber); 22447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, " -f reads a service list from 'file'\n"); 22547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, " -b forces daemon (background) mode\n"); 22647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, " -P uses 'pidfile' as the PID file\n"); 22747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, " (default is '%s')\n", kDefaultPIDFile); 22847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, " only meaningful if -b also specified\n"); 22947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, " -x stores name=val in TXT record (default is empty).\n"); 23047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, " MUST be the last command-line argument;\n"); 23147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, " all subsequent arguments after -x are treated as name=val pairs.\n"); 23247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt} 23347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 23447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic mDNSBool gAvoidPort53 = mDNStrue; 23547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic const char *gServiceName = ""; 23647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic const char *gServiceType = kDefaultServiceType; 23747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic const char *gServiceDomain = kDefaultServiceDomain; 23847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic mDNSu8 gServiceText[sizeof(RDataBody)]; 23947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic mDNSu16 gServiceTextLen = 0; 24047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic int gPortNumber = kDefaultPortNumber; 24147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic const char *gServiceFile = ""; 24247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic mDNSBool gDaemon = mDNSfalse; 24347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic const char *gPIDFile = kDefaultPIDFile; 24447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 24547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic void ParseArguments(int argc, char **argv) 24647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Parses our command line arguments into the global variables 24747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // listed above. 24847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{ 24947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int ch; 25047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 25147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Set gProgramName to the last path component of argv[0] 25247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 25347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gProgramName = strrchr(argv[0], '/'); 25447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (gProgramName == NULL) { 25547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gProgramName = argv[0]; 25647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } else { 25747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gProgramName += 1; 25847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 25947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 26047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Parse command line options using getopt. 26147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 26247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt do { 26347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ch = getopt(argc, argv, "v:rn:t:d:p:f:dP:bx"); 26447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (ch != -1) { 26547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt switch (ch) { 26647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt case 'v': 26747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gMDNSPlatformPosixVerboseLevel = atoi(optarg); 26847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (gMDNSPlatformPosixVerboseLevel < 0 || gMDNSPlatformPosixVerboseLevel > 2) { 26947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, 27047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt "%s: Verbose mode must be in the range 0..2\n", 27147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gProgramName); 27247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt exit(1); 27347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 27447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt break; 27547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt case 'r': 27647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gAvoidPort53 = mDNSfalse; 27747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt break; 27847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt case 'n': 27947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gServiceName = optarg; 28047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( ! CheckThatRichTextNameIsUsable(gServiceName, mDNStrue) ) { 28147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt exit(1); 28247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 28347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt break; 28447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt case 't': 28547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gServiceType = optarg; 28647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( ! CheckThatServiceTypeIsUsable(gServiceType, mDNStrue) ) { 28747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt exit(1); 28847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 28947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt break; 29047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt case 'd': 29147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gServiceDomain = optarg; 29247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt break; 29347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt case 'p': 29447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gPortNumber = atol(optarg); 29547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( ! CheckThatPortNumberIsUsable(gPortNumber, mDNStrue) ) { 29647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt exit(1); 29747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 29847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt break; 29947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt case 'f': 30047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gServiceFile = optarg; 30147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt break; 30247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt case 'b': 30347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gDaemon = mDNStrue; 30447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt break; 30547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt case 'P': 30647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gPIDFile = optarg; 30747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt break; 30847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt case 'x': 30947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt while (optind < argc) 31047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 31147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gServiceText[gServiceTextLen] = strlen(argv[optind]); 31247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSPlatformMemCopy(gServiceText+gServiceTextLen+1, argv[optind], gServiceText[gServiceTextLen]); 31347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gServiceTextLen += 1 + gServiceText[gServiceTextLen]; 31447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt optind++; 31547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 31647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ch = -1; 31747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt break; 31847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt case '?': 31947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt default: 32047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt PrintUsage(); 32147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt exit(1); 32247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt break; 32347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 32447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 32547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } while (ch != -1); 32647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 32747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Check for any left over command line arguments. 32847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 32947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (optind != argc) { 33047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt PrintUsage(); 33147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, "%s: Unexpected argument '%s'\n", gProgramName, argv[optind]); 33247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt exit(1); 33347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 33447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 33547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Check for inconsistency between the arguments. 33647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 33747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( (gServiceName[0] == 0) && (gServiceFile[0] == 0) ) { 33847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt PrintUsage(); 33947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, "%s: You must specify a service name to register (-n) or a service file (-f).\n", gProgramName); 34047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt exit(1); 34147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 34247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt} 34347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 34447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if COMPILER_LIKES_PRAGMA_MARK 34547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#pragma mark ***** Registration 34647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif 34747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 34847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalttypedef struct PosixService PosixService; 34947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 35047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstruct PosixService { 35147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ServiceRecordSet coreServ; 35247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt PosixService *next; 35347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int serviceID; 35447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt}; 35547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 35647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic PosixService *gServiceList = NULL; 35747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 35847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic void RegistrationCallback(mDNS *const m, ServiceRecordSet *const thisRegistration, mStatus status) 35947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // mDNS core calls this routine to tell us about the status of 36047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // our registration. The appropriate action to take depends 36147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // entirely on the value of status. 36247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{ 36347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt switch (status) { 36447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 36547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt case mStatus_NoError: 36647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt debugf("Callback: %##s Name Registered", thisRegistration->RR_SRV.resrec.name->c); 36747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Do nothing; our name was successfully registered. We may 36847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // get more call backs in the future. 36947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt break; 37047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 37147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt case mStatus_NameConflict: 37247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt debugf("Callback: %##s Name Conflict", thisRegistration->RR_SRV.resrec.name->c); 37347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 37447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // In the event of a conflict, this sample RegistrationCallback 37547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // just calls mDNS_RenameAndReregisterService to automatically 37647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // pick a new unique name for the service. For a device such as a 37747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // printer, this may be appropriate. For a device with a user 37847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // interface, and a screen, and a keyboard, the appropriate response 37947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // may be to prompt the user and ask them to choose a new name for 38047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // the service. 38147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // 38247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Also, what do we do if mDNS_RenameAndReregisterService returns an 38347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // error. Right now I have no place to send that error to. 38447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 38547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt status = mDNS_RenameAndReregisterService(m, thisRegistration, mDNSNULL); 38647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt assert(status == mStatus_NoError); 38747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt break; 38847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 38947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt case mStatus_MemFree: 39047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt debugf("Callback: %##s Memory Free", thisRegistration->RR_SRV.resrec.name->c); 39147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 39247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // When debugging is enabled, make sure that thisRegistration 39347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // is not on our gServiceList. 39447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 39547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt #if !defined(NDEBUG) 39647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 39747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt PosixService *cursor; 39847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 39947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt cursor = gServiceList; 40047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt while (cursor != NULL) { 40147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt assert(&cursor->coreServ != thisRegistration); 40247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt cursor = cursor->next; 40347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 40447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 40547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt #endif 40647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt free(thisRegistration); 40747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt break; 40847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 40947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt default: 41047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt debugf("Callback: %##s Unknown Status %ld", thisRegistration->RR_SRV.resrec.name->c, status); 41147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt break; 41247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 41347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt} 41447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 41547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic int gServiceID = 0; 41647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 41747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic mStatus RegisterOneService(const char * richTextName, 41847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt const char * serviceType, 41947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt const char * serviceDomain, 42047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt const mDNSu8 text[], 42147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSu16 textLen, 42247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt long portNumber) 42347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{ 42447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mStatus status; 42547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt PosixService * thisServ; 42647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt domainlabel name; 42747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt domainname type; 42847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt domainname domain; 42947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 43047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt status = mStatus_NoError; 43147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt thisServ = (PosixService *) malloc(sizeof(*thisServ)); 43247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (thisServ == NULL) { 43347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt status = mStatus_NoMemoryErr; 43447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 43547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (status == mStatus_NoError) { 43647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt MakeDomainLabelFromLiteralString(&name, richTextName); 43747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt MakeDomainNameFromDNSNameString(&type, serviceType); 43847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt MakeDomainNameFromDNSNameString(&domain, serviceDomain); 43947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt status = mDNS_RegisterService(&mDNSStorage, &thisServ->coreServ, 44047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt &name, &type, &domain, // Name, type, domain 44147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt NULL, mDNSOpaque16fromIntVal(portNumber), 44247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt text, textLen, // TXT data, length 44347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt NULL, 0, // Subtypes 44447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSInterface_Any, // Interface ID 44547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt RegistrationCallback, thisServ, 0); // Callback, context, flags 44647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 44747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (status == mStatus_NoError) { 44847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt thisServ->serviceID = gServiceID; 44947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gServiceID += 1; 45047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 45147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt thisServ->next = gServiceList; 45247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gServiceList = thisServ; 45347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 45447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (gMDNSPlatformPosixVerboseLevel > 0) { 45547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, 45647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt "%s: Registered service %d, name \"%s\", type \"%s\", domain \"%s\", port %ld\n", 45747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gProgramName, 45847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt thisServ->serviceID, 45947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt richTextName, 46047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt serviceType, 46147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt serviceDomain, 46247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt portNumber); 46347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 46447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } else { 46547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (thisServ != NULL) { 46647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt free(thisServ); 46747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 46847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 46947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return status; 47047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt} 47147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 47247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic mDNSBool ReadALine(char *buf, size_t bufSize, FILE *fp, mDNSBool skipBlankLines) 47347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{ 47447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt size_t len; 47547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSBool readNextLine; 47647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 47747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt do { 47847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt readNextLine = mDNSfalse; 47947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 48047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (fgets(buf, bufSize, fp) == NULL) 48147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return mDNSfalse; // encountered EOF or an error condition 48247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 48347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // These first characters indicate a blank line. 48447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (buf[0] == ' ' || buf[0] == '\t' || buf[0] == '\r' || buf[0] == '\n') { 48547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!skipBlankLines) 48647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return mDNSfalse; 48747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt readNextLine = mDNStrue; 48847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 48947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // always skip comment lines 49047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (buf[0] == '#') 49147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt readNextLine = mDNStrue; 49247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 49347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } while (readNextLine); 49447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 49547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt len = strlen( buf); 49647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( buf[len - 1] == '\r' || buf[len - 1] == '\n') 49747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt buf[len - 1] = '\0'; 49847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 49947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return mDNStrue; 50047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt} 50147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 50247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic mStatus RegisterServicesInFile(const char *filePath) 50347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{ 50447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mStatus status = mStatus_NoError; 50547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt FILE * fp = fopen(filePath, "r"); 50647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 50747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (fp == NULL) { 50847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return mStatus_UnknownErr; 50947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 51047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 51147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (gMDNSPlatformPosixVerboseLevel > 1) 51247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, "Parsing %s for services\n", filePath); 51347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 51447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt do { 51547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt char nameBuf[256]; 51647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt char * name = nameBuf; 51747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt char type[256]; 51847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt const char *dom = kDefaultServiceDomain; 51947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt char rawText[1024]; 52047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSu8 text[sizeof(RDataBody)]; 52147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt unsigned int textLen = 0; 52247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt char port[256]; 52347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt char *p; 52447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 52547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Read the service name, type, port, and optional text record fields. 52647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Skip blank lines while looking for the next service name. 52747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (! ReadALine(name, sizeof(nameBuf), fp, mDNStrue)) 52847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt break; 52947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 53047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Special case that allows service name to begin with a '#' 53147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // character by escaping it with a '\' to distiguish it from 53247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // a comment line. Remove the leading '\' here before 53347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // registering the service. 53447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (name[0] == '\\' && name[1] == '#') 53547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt name++; 53647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 53747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (gMDNSPlatformPosixVerboseLevel > 1) 53847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, "Service name: \"%s\"\n", name); 53947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 54047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Don't skip blank lines in calls to ReadAline() after finding the 54147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // service name since the next blank line indicates the end 54247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // of this service record. 54347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (! ReadALine(type, sizeof(type), fp, mDNSfalse)) 54447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt break; 54547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 54647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // see if a domain name is specified 54747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt p = type; 54847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt while (*p && *p != ' ' && *p != '\t') p++; 54947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (*p) { 55047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt *p = 0; // NULL terminate the <type>.<protocol> string 55147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // skip any leading whitespace before domain name 55247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt p++; 55347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt while (*p && (*p == ' ' || *p == '\t')) p++; 55447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (*p) 55547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt dom = p; 55647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 55747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (gMDNSPlatformPosixVerboseLevel > 1) { 55847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, "Service type: \"%s\"\n", type); 55947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, "Service domain: \"%s\"\n", dom); 56047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 56147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 56247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (! ReadALine(port, sizeof(port), fp, mDNSfalse)) 56347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt break; 56447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (gMDNSPlatformPosixVerboseLevel > 1) 56547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, "Service port: %s\n", port); 56647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 56747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( ! CheckThatRichTextNameIsUsable(name, mDNStrue) 56847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt || ! CheckThatServiceTypeIsUsable(type, mDNStrue) 56947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt || ! CheckThatPortNumberIsUsable(atol(port), mDNStrue)) 57047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt break; 57147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 57247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // read the TXT record fields 57347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt while (1) { 57447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int len; 57547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!ReadALine(rawText, sizeof(rawText), fp, mDNSfalse)) break; 57647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (gMDNSPlatformPosixVerboseLevel > 1) 57747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, "Text string: \"%s\"\n", rawText); 57847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt len = strlen(rawText); 57947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (len <= 255) 58047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 58147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt unsigned int newlen = textLen + 1 + len; 58247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (len == 0 || newlen >= sizeof(text)) break; 58347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt text[textLen] = len; 58447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSPlatformMemCopy(text + textLen + 1, rawText, len); 58547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt textLen = newlen; 58647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 58747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else 58847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, "%s: TXT attribute too long for name = %s, type = %s, port = %s\n", 58947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gProgramName, name, type, port); 59047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 59147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 59247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt status = RegisterOneService(name, type, dom, text, textLen, atol(port)); 59347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (status != mStatus_NoError) { 59447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // print error, but try to read and register other services in the file 59547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, "%s: Failed to register service, name \"%s\", type \"%s\", domain \"%s\", port %s\n", 59647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gProgramName, name, type, dom, port); 59747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 59847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 59947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } while (!feof(fp)); 60047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 60147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!feof(fp)) { 60247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, "%s: Error reading service file %s\n", gProgramName, filePath); 60347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt status = mStatus_UnknownErr; 60447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 60547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 606f48f8a2e3417f93bc1f45930dbf9c4ea7523523dDave Platt { 607f48f8a2e3417f93bc1f45930dbf9c4ea7523523dDave Platt// __ANDROID__ : replaced assert(fclose(..)) 608f48f8a2e3417f93bc1f45930dbf9c4ea7523523dDave Platt int fp_closed = fclose(fp); 609f48f8a2e3417f93bc1f45930dbf9c4ea7523523dDave Platt assert(0 == fp_closed); 610f48f8a2e3417f93bc1f45930dbf9c4ea7523523dDave Platt } 61147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 61247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return status; 61347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt} 61447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 61547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic mStatus RegisterOurServices(void) 61647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{ 61747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mStatus status; 61847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 61947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt status = mStatus_NoError; 62047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (gServiceName[0] != 0) { 62147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt status = RegisterOneService(gServiceName, 62247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gServiceType, 62347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gServiceDomain, 62447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gServiceText, gServiceTextLen, 62547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gPortNumber); 62647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 62747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (status == mStatus_NoError && gServiceFile[0] != 0) { 62847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt status = RegisterServicesInFile(gServiceFile); 62947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 63047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return status; 63147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt} 63247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 63347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic void DeregisterOurServices(void) 63447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{ 63547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt PosixService *thisServ; 63647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int thisServID; 63747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 63847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt while (gServiceList != NULL) { 63947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt thisServ = gServiceList; 64047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gServiceList = thisServ->next; 64147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 64247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt thisServID = thisServ->serviceID; 64347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 64447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNS_DeregisterService(&mDNSStorage, &thisServ->coreServ); 64547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 64647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (gMDNSPlatformPosixVerboseLevel > 0) { 64747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, 64847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt "%s: Deregistered service %d\n", 64947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gProgramName, 65047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt thisServ->serviceID); 65147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 65247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 65347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt} 65447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 65547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if COMPILER_LIKES_PRAGMA_MARK 65647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#pragma mark **** Main 65747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif 65847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 65947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltint main(int argc, char **argv) 66047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt{ 66147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mStatus status; 66247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int result; 66347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 66447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Parse our command line arguments. This won't come back if there's an error. 66547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 66647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ParseArguments(argc, argv); 66747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 66847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // If we're told to run as a daemon, then do that straight away. 66947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Note that we don't treat the inability to create our PID 67047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // file as an error. Also note that we assign getpid to a long 67147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // because printf has no format specified for pid_t. 67247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 67347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (gDaemon) { 67447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int result; 67547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (gMDNSPlatformPosixVerboseLevel > 0) { 67647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, "%s: Starting in daemon mode\n", gProgramName); 67747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 67847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt result = daemon(0,0); 67947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (result == 0) { 68047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt FILE *fp; 68147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int junk; 68247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 68347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fp = fopen(gPIDFile, "w"); 68447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (fp != NULL) { 68547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(fp, "%ld\n", (long) getpid()); 68647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt junk = fclose(fp); 68747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt assert(junk == 0); 68847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 68947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } else { 69047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, "%s: Could not run as daemon - exiting\n", gProgramName); 69147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt exit(result); 69247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 69347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } else { 69447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (gMDNSPlatformPosixVerboseLevel > 0) { 69547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, "%s: Starting in foreground mode, PID %ld\n", gProgramName, (long) getpid()); 69647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 69747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 69847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 69947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt status = mDNS_Init(&mDNSStorage, &PlatformStorage, 70047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNS_Init_NoCache, mDNS_Init_ZeroCacheSize, 70147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNS_Init_AdvertiseLocalAddresses, 70247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNS_Init_NoInitCallback, mDNS_Init_NoInitCallbackContext); 70347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (status != mStatus_NoError) return(2); 70447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 70547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt status = RegisterOurServices(); 70647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (status != mStatus_NoError) return(2); 70747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 70847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt signal(SIGHUP, HandleSigHup); // SIGHUP has to be sent by kill -HUP <pid> 70947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt signal(SIGINT, HandleSigInt); // SIGINT is what you get for a Ctrl-C 71047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt signal(SIGQUIT, HandleSigQuit); // SIGQUIT is what you get for a Ctrl-\ (indeed) 71147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt signal(SIGUSR1, HandleSigUsr1); // SIGUSR1 has to be sent by kill -USR1 <pid> 71247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 71347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt while (!gStopNow) 71447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 71547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int nfds = 0; 71647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fd_set readfds; 71747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt struct timeval timeout; 71847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int result; 71947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 72047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // 1. Set up the fd_set as usual here. 72147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // This example client has no file descriptors of its own, 72247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // but a real application would call FD_SET to add them to the set here 72347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt FD_ZERO(&readfds); 72447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 72547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // 2. Set up the timeout. 72647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // This example client has no other work it needs to be doing, 72747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // so we set an effectively infinite timeout 72847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt timeout.tv_sec = 0x3FFFFFFF; 72947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt timeout.tv_usec = 0; 73047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 73147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // 3. Give the mDNSPosix layer a chance to add its information to the fd_set and timeout 73247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSPosixGetFDSet(&mDNSStorage, &nfds, &readfds, &timeout); 73347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 73447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // 4. Call select as normal 73547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt verbosedebugf("select(%d, %d.%06d)", nfds, timeout.tv_sec, timeout.tv_usec); 73647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt result = select(nfds, &readfds, NULL, NULL, &timeout); 73747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 73847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (result < 0) 73947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 74047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt verbosedebugf("select() returned %d errno %d", result, errno); 74147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (errno != EINTR) gStopNow = mDNStrue; 74247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else 74347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 74447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (gReceivedSigUsr1) 74547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 74647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gReceivedSigUsr1 = mDNSfalse; 74747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gMDNSPlatformPosixVerboseLevel += 1; 74847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (gMDNSPlatformPosixVerboseLevel > 2) 74947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gMDNSPlatformPosixVerboseLevel = 0; 75047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( gMDNSPlatformPosixVerboseLevel > 0 ) 75147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, "\nVerbose level %d\n", gMDNSPlatformPosixVerboseLevel); 75247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 75347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (gReceivedSigHup) 75447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 75547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (gMDNSPlatformPosixVerboseLevel > 0) 75647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, "\nSIGHUP\n"); 75747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gReceivedSigHup = mDNSfalse; 75847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DeregisterOurServices(); 75947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt status = mDNSPlatformPosixRefreshInterfaceList(&mDNSStorage); 76047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (status != mStatus_NoError) break; 76147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt status = RegisterOurServices(); 76247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (status != mStatus_NoError) break; 76347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 76447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 76547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 76647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else 76747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 76847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // 5. Call mDNSPosixProcessFDSet to let the mDNSPosix layer do its work 76947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSPosixProcessFDSet(&mDNSStorage, &readfds); 77047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 77147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // 6. This example client has no other work it needs to be doing, 77247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // but a real client would do its work here 77347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // ... (do work) ... 77447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 77547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 77647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 77747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt debugf("Exiting"); 77847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 77947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DeregisterOurServices(); 78047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNS_Close(&mDNSStorage); 78147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 78247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (status == mStatus_NoError) { 78347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt result = 0; 78447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } else { 78547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt result = 2; 78647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 78747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if ( (result != 0) || (gMDNSPlatformPosixVerboseLevel > 0) ) { 78847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, "%s: Finished with status %d, result %d\n", gProgramName, (int)status, result); 78947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 79047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 79147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return result; 79247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt} 793