1 /* -*- Mode: C; tab-width: 4 -*-
3 * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved.
5 * @APPLE_LICENSE_HEADER_START@
7 * This file contains Original Code and/or Modifications of Original Code
8 * as defined in and that are subject to the Apple Public Source License
9 * Version 2.0 (the 'License'). You may not use this file except in
10 * compliance with the License. Please obtain a copy of the License at
11 * http://www.opensource.apple.com/apsl/ and read it before using this
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
19 * Please see the License for the specific language governing rights and
20 * limitations under the License.
22 * @APPLE_LICENSE_HEADER_END@
26 Contains: main & associated Application layer for mDNSResponder on Linux.
28 Change History (most recent first):
30 $Log: PosixDaemon.c,v $
31 Revision 1.27 2005/02/04 00:39:59 cheshire
32 Move ParseDNSServers() from PosixDaemon.c to mDNSPosix.c so all Posix client layers can use it
34 Revision 1.26 2005/02/02 02:21:30 cheshire
35 Update references to "mDNSResponder" to say "mdnsd" instead
37 Revision 1.25 2005/01/27 20:01:50 cheshire
38 udsSupportRemoveFDFromEventLoop() needs to close the file descriptor as well
40 Revision 1.24 2005/01/19 19:20:49 ksekar
41 <rdar://problem/3960191> Need a way to turn off domain discovery
43 Revision 1.23 2004/12/16 20:17:11 cheshire
44 <rdar://problem/3324626> Cache memory management improvements
46 Revision 1.22 2004/12/10 13:12:08 cheshire
47 Create no-op function RecordUpdatedNiceLabel(), required by uds_daemon.c
49 Revision 1.21 2004/12/01 20:57:20 ksekar
50 <rdar://problem/3873921> Wide Area Service Discovery must be split-DNS aware
52 Revision 1.20 2004/12/01 04:28:43 cheshire
53 <rdar://problem/3872803> Darwin patches for Solaris and Suse
54 Use version of daemon() provided in mDNSUNP.c instead of local copy
56 Revision 1.19 2004/12/01 03:30:29 cheshire
57 <rdar://problem/3889346> Add Unicast DNS support to mDNSPosix
59 Revision 1.18 2004/11/30 22:45:59 cheshire
62 Revision 1.17 2004/11/30 22:18:59 cheshire
63 <rdar://problem/3889351> Posix needs to read the list of unicast DNS servers and set server list
65 Revision 1.16 2004/09/21 21:05:12 cheshire
66 Move duplicate code out of mDNSMacOSX/daemon.c and mDNSPosix/PosixDaemon.c,
67 into mDNSShared/uds_daemon.c
69 Revision 1.15 2004/09/17 01:08:53 cheshire
70 Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
71 The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
72 declared in that file are ONLY appropriate to single-address-space embedded applications.
73 For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
75 Revision 1.14 2004/09/16 00:24:49 cheshire
76 <rdar://problem/3803162> Fix unsafe use of mDNSPlatformTimeNow()
78 Revision 1.13 2004/08/11 01:59:41 cheshire
79 Remove "mDNS *globalInstance" parameter from udsserver_init()
81 Revision 1.12 2004/06/28 23:19:19 cheshire
82 Fix "Daemon_Init declared but never defined" warning on Linux
84 Revision 1.11 2004/06/25 00:26:27 rpantos
85 Changes to fix the Posix build on Solaris.
87 Revision 1.10 2004/06/08 04:59:40 cheshire
88 Tidy up wording -- log messages are already prefixed with "mDNSResponder", so don't need to repeat it
90 Revision 1.9 2004/05/29 00:14:20 rpantos
91 <rdar://problem/3508093> Runtime check to disable prod mdnsd on OS X.
93 Revision 1.8 2004/04/07 01:19:04 cheshire
94 Hash slot value should be unsigned
96 Revision 1.7 2004/02/14 06:34:57 cheshire
97 Use LogMsg instead of fprintf( stderr
99 Revision 1.6 2004/02/14 01:10:42 rpantos
100 Allow daemon to run if 'nobody' is not defined, with a warning. (For Roku HD1000.)
102 Revision 1.5 2004/02/05 07:45:43 cheshire
105 Revision 1.4 2004/01/28 21:14:23 cheshire
106 Reconcile debug_mode and gDebugLogging into a single flag (mDNS_DebugMode)
108 Revision 1.3 2004/01/19 19:51:46 cheshire
109 Fix compiler error (mixed declarations and code) on some versions of Linux
111 Revision 1.2 2003/12/11 03:03:51 rpantos
112 Clean up mDNSPosix so that it builds on OS X again.
114 Revision 1.1 2003/12/08 20:47:02 rpantos
115 Add support for mDNSResponder on Linux.
126 #include <sys/types.h>
128 #include "mDNSEmbeddedAPI.h"
129 #include "mDNSDebug.h"
130 #include "mDNSPosix.h"
131 #include "uds_daemon.h"
132 #include "PlatformCommon.h"
134 #define CONFIG_FILE "/etc/mdnsd.conf"
135 static domainname DynDNSZone
; // Default wide-area zone for service registration
136 static domainname DynDNSHostname
;
138 #define RR_CACHE_SIZE 500
139 static CacheEntity gRRCache
[RR_CACHE_SIZE
];
141 extern const char mDNSResponderVersionString
[];
143 static void Reconfigure(mDNS
*m
)
146 mDNS_SetPrimaryInterfaceInfo(m
, NULL
, NULL
);
147 mDNS_DeleteDNSServers(m
);
148 if (ParseDNSServers(m
, uDNS_SERVERS_FILE
) < 0)
149 LogMsg("Unable to parse DNS server list. Unicast DNS-SD unavailable");
150 ReadDDNSSettingsFromConfFile(m
, CONFIG_FILE
, &DynDNSHostname
, &DynDNSZone
, NULL
);
151 FindDefaultRouteIP(&DynDNSIP
);
152 if (DynDNSHostname
.c
[0]) mDNS_AddDynDNSHostName(m
, &DynDNSHostname
, NULL
, NULL
);
153 if (DynDNSIP
.type
) mDNS_SetPrimaryInterfaceInfo(m
, &DynDNSIP
, NULL
);
156 // Do appropriate things at startup with command line arguments. Calls exit() if unhappy.
157 static void ParseCmdLinArgs(int argc
, char **argv
)
161 if (0 == strcmp(argv
[1], "-debug")) mDNS_DebugMode
= mDNStrue
;
162 else printf("Usage: %s [-debug]\n", argv
[0]);
167 int result
= daemon(0, 0);
168 if (result
!= 0) { LogMsg("Could not run as daemon - exiting"); exit(result
); }
170 LogMsg("The POSIX mdnsd should only be used on OS X for testing - exiting");
176 static void DumpStateLog(mDNS
*const m
)
177 // Dump a little log of what we've been up to.
179 LogMsgIdent(mDNSResponderVersionString
, "---- BEGIN STATE LOG ----");
181 LogMsgIdent(mDNSResponderVersionString
, "---- END STATE LOG ----");
184 static mStatus
MainLoop(mDNS
*m
) // Loop until we quit.
187 mDNSBool gotData
= mDNSfalse
;
189 mDNSPosixListenForSignalInEventLoop(SIGINT
);
190 mDNSPosixListenForSignalInEventLoop(SIGTERM
);
191 mDNSPosixListenForSignalInEventLoop(SIGUSR1
);
192 mDNSPosixListenForSignalInEventLoop(SIGPIPE
);
193 mDNSPosixListenForSignalInEventLoop(SIGHUP
) ;
197 // Work out how long we expect to sleep before the next scheduled task
198 struct timeval timeout
;
201 // Only idle if we didn't find any data the last time around
204 mDNSs32 nextTimerEvent
= mDNS_Execute(m
);
205 nextTimerEvent
= udsserver_idle(nextTimerEvent
);
206 ticks
= nextTimerEvent
- mDNS_TimeNow(m
);
207 if (ticks
< 1) ticks
= 1;
209 else // otherwise call EventLoop again with 0 timemout
212 timeout
.tv_sec
= ticks
/ mDNSPlatformOneSecond
;
213 timeout
.tv_usec
= (ticks
% mDNSPlatformOneSecond
) * 1000000 / mDNSPlatformOneSecond
;
215 (void) mDNSPosixRunEventLoopOnce(m
, &timeout
, &signals
, &gotData
);
217 if (sigismember(&signals
, SIGHUP
)) Reconfigure(m
);
218 if (sigismember(&signals
, SIGUSR1
)) DumpStateLog(m
);
219 // SIGPIPE happens when we try to write to a dead client; death should be detected soon in request_callback() and cleaned up.
220 if (sigismember(&signals
, SIGPIPE
)) LogMsg("Received SIGPIPE - ignoring");
221 if (sigismember(&signals
, SIGINT
) || sigismember(&signals
, SIGTERM
)) break;
226 int main(int argc
, char **argv
)
228 #define mDNSRecord mDNSStorage
229 mDNS_PlatformSupport platformStorage
;
232 bzero(&mDNSRecord
, sizeof mDNSRecord
);
233 bzero(&platformStorage
, sizeof platformStorage
);
235 ParseCmdLinArgs(argc
, argv
);
237 LogMsgIdent(mDNSResponderVersionString
, "starting");
239 err
= mDNS_Init(&mDNSRecord
, &platformStorage
, gRRCache
, RR_CACHE_SIZE
, mDNS_Init_AdvertiseLocalAddresses
,
240 mDNS_Init_NoInitCallback
, mDNS_Init_NoInitCallbackContext
);
242 if (mStatus_NoError
== err
)
243 err
= udsserver_init();
245 Reconfigure(&mDNSRecord
);
247 // Now that we're finished with anything privileged, switch over to running as "nobody"
248 if (mStatus_NoError
== err
)
250 const struct passwd
*pw
= getpwnam("nobody");
254 LogMsg("WARNING: mdnsd continuing as root because user \"nobody\" does not exist");
257 if (mStatus_NoError
== err
)
258 err
= MainLoop(&mDNSRecord
);
260 LogMsgIdent(mDNSResponderVersionString
, "stopping");
262 mDNS_Close(&mDNSRecord
);
264 if (udsserver_exit() < 0)
265 LogMsg("ExitCallback: udsserver_exit failed");
267 #if MDNS_DEBUGMSGS > 0
268 printf("mDNSResponder exiting normally with %ld\n", err
);
274 // uds_daemon support ////////////////////////////////////////////////////////////
276 #if MDNS_MALLOC_DEBUGGING >= 2
277 #define LogMalloc LogMsg
279 #define LogMalloc(ARGS...) ((void)0)
282 mStatus
udsSupportAddFDToEventLoop(int fd
, udsEventCallback callback
, void *context
)
283 /* Support routine for uds_daemon.c */
285 // Depends on the fact that udsEventCallback == mDNSPosixEventCallback
286 return mDNSPosixAddFDToEventLoop(fd
, callback
, context
);
289 mStatus
udsSupportRemoveFDFromEventLoop(int fd
) // Note: This also CLOSES the file descriptor
291 return mDNSPosixRemoveFDFromEventLoop(fd
);
295 mDNSexport
void RecordUpdatedNiceLabel(mDNS
*const m
, mDNSs32 delay
)
302 #if MACOSX_MDNS_MALLOC_DEBUGGING >= 1
304 void *mallocL(char *msg
, unsigned int size
)
306 unsigned long *mem
= malloc(size
+8);
309 LogMsg("malloc( %s : %d ) failed", msg
, size
);
314 LogMalloc("malloc( %s : %lu ) = %p", msg
, size
, &mem
[2]);
317 //bzero(&mem[2], size);
318 memset(&mem
[2], 0xFF, size
);
319 // validatelists(&mDNSStorage);
324 void freeL(char *msg
, void *x
)
327 LogMsg("free( %s @ NULL )!", msg
);
330 unsigned long *mem
= ((unsigned long *)x
) - 2;
331 if (mem
[0] != 0xDEAD1234)
332 { LogMsg("free( %s @ %p ) !!!! NOT ALLOCATED !!!!", msg
, &mem
[2]); return; }
334 { LogMsg("free( %s : %ld @ %p) too big!", msg
, mem
[1], &mem
[2]); return; }
335 LogMalloc("free( %s : %ld @ %p)", msg
, mem
[1], &mem
[2]);
336 //bzero(mem, mem[1]+8);
337 memset(mem
, 0xDD, mem
[1]+8);
338 // validatelists(&mDNSStorage);
343 #endif // MACOSX_MDNS_MALLOC_DEBUGGING >= 1
345 // For convenience when using the "strings" command, this is the last thing in the file
346 #if mDNSResponderVersion > 1
347 mDNSexport
const char mDNSResponderVersionString
[] = "mDNSResponder-" STRINGIFY(mDNSResponderVersion
) " (" __DATE__
" " __TIME__
") ";
349 mDNSexport
const char mDNSResponderVersionString
[] = "mDNSResponder (Engineering Build) (" __DATE__
" " __TIME__
") ";