]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSPosix/PosixDaemon.c
mDNSResponder-107.tar.gz
[apple/mdnsresponder.git] / mDNSPosix / PosixDaemon.c
1 /* -*- Mode: C; tab-width: 4 -*-
2 *
3 * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved.
4 *
5 * @APPLE_LICENSE_HEADER_START@
6 *
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
12 * file.
13 *
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.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23
24 File: daemon.c
25
26 Contains: main & associated Application layer for mDNSResponder on Linux.
27
28 Change History (most recent first):
29
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
33
34 Revision 1.26 2005/02/02 02:21:30 cheshire
35 Update references to "mDNSResponder" to say "mdnsd" instead
36
37 Revision 1.25 2005/01/27 20:01:50 cheshire
38 udsSupportRemoveFDFromEventLoop() needs to close the file descriptor as well
39
40 Revision 1.24 2005/01/19 19:20:49 ksekar
41 <rdar://problem/3960191> Need a way to turn off domain discovery
42
43 Revision 1.23 2004/12/16 20:17:11 cheshire
44 <rdar://problem/3324626> Cache memory management improvements
45
46 Revision 1.22 2004/12/10 13:12:08 cheshire
47 Create no-op function RecordUpdatedNiceLabel(), required by uds_daemon.c
48
49 Revision 1.21 2004/12/01 20:57:20 ksekar
50 <rdar://problem/3873921> Wide Area Service Discovery must be split-DNS aware
51
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
55
56 Revision 1.19 2004/12/01 03:30:29 cheshire
57 <rdar://problem/3889346> Add Unicast DNS support to mDNSPosix
58
59 Revision 1.18 2004/11/30 22:45:59 cheshire
60 Minor code tidying
61
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
64
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
68
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.
74
75 Revision 1.14 2004/09/16 00:24:49 cheshire
76 <rdar://problem/3803162> Fix unsafe use of mDNSPlatformTimeNow()
77
78 Revision 1.13 2004/08/11 01:59:41 cheshire
79 Remove "mDNS *globalInstance" parameter from udsserver_init()
80
81 Revision 1.12 2004/06/28 23:19:19 cheshire
82 Fix "Daemon_Init declared but never defined" warning on Linux
83
84 Revision 1.11 2004/06/25 00:26:27 rpantos
85 Changes to fix the Posix build on Solaris.
86
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
89
90 Revision 1.9 2004/05/29 00:14:20 rpantos
91 <rdar://problem/3508093> Runtime check to disable prod mdnsd on OS X.
92
93 Revision 1.8 2004/04/07 01:19:04 cheshire
94 Hash slot value should be unsigned
95
96 Revision 1.7 2004/02/14 06:34:57 cheshire
97 Use LogMsg instead of fprintf( stderr
98
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.)
101
102 Revision 1.5 2004/02/05 07:45:43 cheshire
103 Add Log header
104
105 Revision 1.4 2004/01/28 21:14:23 cheshire
106 Reconcile debug_mode and gDebugLogging into a single flag (mDNS_DebugMode)
107
108 Revision 1.3 2004/01/19 19:51:46 cheshire
109 Fix compiler error (mixed declarations and code) on some versions of Linux
110
111 Revision 1.2 2003/12/11 03:03:51 rpantos
112 Clean up mDNSPosix so that it builds on OS X again.
113
114 Revision 1.1 2003/12/08 20:47:02 rpantos
115 Add support for mDNSResponder on Linux.
116 */
117
118 #include <stdio.h>
119 #include <string.h>
120 #include <unistd.h>
121 #include <stdlib.h>
122 #include <signal.h>
123 #include <errno.h>
124 #include <fcntl.h>
125 #include <pwd.h>
126 #include <sys/types.h>
127
128 #include "mDNSEmbeddedAPI.h"
129 #include "mDNSDebug.h"
130 #include "mDNSPosix.h"
131 #include "uds_daemon.h"
132 #include "PlatformCommon.h"
133
134 #define CONFIG_FILE "/etc/mdnsd.conf"
135 static domainname DynDNSZone; // Default wide-area zone for service registration
136 static domainname DynDNSHostname;
137
138 #define RR_CACHE_SIZE 500
139 static CacheEntity gRRCache[RR_CACHE_SIZE];
140
141 extern const char mDNSResponderVersionString[];
142
143 static void Reconfigure(mDNS *m)
144 {
145 mDNSAddr DynDNSIP;
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);
154 }
155
156 // Do appropriate things at startup with command line arguments. Calls exit() if unhappy.
157 static void ParseCmdLinArgs(int argc, char **argv)
158 {
159 if (argc > 1)
160 {
161 if (0 == strcmp(argv[1], "-debug")) mDNS_DebugMode = mDNStrue;
162 else printf("Usage: %s [-debug]\n", argv[0]);
163 }
164
165 if (!mDNS_DebugMode)
166 {
167 int result = daemon(0, 0);
168 if (result != 0) { LogMsg("Could not run as daemon - exiting"); exit(result); }
169 #if __APPLE__
170 LogMsg("The POSIX mdnsd should only be used on OS X for testing - exiting");
171 exit(-1);
172 #endif
173 }
174 }
175
176 static void DumpStateLog(mDNS *const m)
177 // Dump a little log of what we've been up to.
178 {
179 LogMsgIdent(mDNSResponderVersionString, "---- BEGIN STATE LOG ----");
180 udsserver_info(m);
181 LogMsgIdent(mDNSResponderVersionString, "---- END STATE LOG ----");
182 }
183
184 static mStatus MainLoop(mDNS *m) // Loop until we quit.
185 {
186 sigset_t signals;
187 mDNSBool gotData = mDNSfalse;
188
189 mDNSPosixListenForSignalInEventLoop(SIGINT);
190 mDNSPosixListenForSignalInEventLoop(SIGTERM);
191 mDNSPosixListenForSignalInEventLoop(SIGUSR1);
192 mDNSPosixListenForSignalInEventLoop(SIGPIPE);
193 mDNSPosixListenForSignalInEventLoop(SIGHUP) ;
194
195 for (; ;)
196 {
197 // Work out how long we expect to sleep before the next scheduled task
198 struct timeval timeout;
199 mDNSs32 ticks;
200
201 // Only idle if we didn't find any data the last time around
202 if (!gotData)
203 {
204 mDNSs32 nextTimerEvent = mDNS_Execute(m);
205 nextTimerEvent = udsserver_idle(nextTimerEvent);
206 ticks = nextTimerEvent - mDNS_TimeNow(m);
207 if (ticks < 1) ticks = 1;
208 }
209 else // otherwise call EventLoop again with 0 timemout
210 ticks = 0;
211
212 timeout.tv_sec = ticks / mDNSPlatformOneSecond;
213 timeout.tv_usec = (ticks % mDNSPlatformOneSecond) * 1000000 / mDNSPlatformOneSecond;
214
215 (void) mDNSPosixRunEventLoopOnce(m, &timeout, &signals, &gotData);
216
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;
222 }
223 return EINTR;
224 }
225
226 int main(int argc, char **argv)
227 {
228 #define mDNSRecord mDNSStorage
229 mDNS_PlatformSupport platformStorage;
230 mStatus err;
231
232 bzero(&mDNSRecord, sizeof mDNSRecord);
233 bzero(&platformStorage, sizeof platformStorage);
234
235 ParseCmdLinArgs(argc, argv);
236
237 LogMsgIdent(mDNSResponderVersionString, "starting");
238
239 err = mDNS_Init(&mDNSRecord, &platformStorage, gRRCache, RR_CACHE_SIZE, mDNS_Init_AdvertiseLocalAddresses,
240 mDNS_Init_NoInitCallback, mDNS_Init_NoInitCallbackContext);
241
242 if (mStatus_NoError == err)
243 err = udsserver_init();
244
245 Reconfigure(&mDNSRecord);
246
247 // Now that we're finished with anything privileged, switch over to running as "nobody"
248 if (mStatus_NoError == err)
249 {
250 const struct passwd *pw = getpwnam("nobody");
251 if (pw != NULL)
252 setuid(pw->pw_uid);
253 else
254 LogMsg("WARNING: mdnsd continuing as root because user \"nobody\" does not exist");
255 }
256
257 if (mStatus_NoError == err)
258 err = MainLoop(&mDNSRecord);
259
260 LogMsgIdent(mDNSResponderVersionString, "stopping");
261
262 mDNS_Close(&mDNSRecord);
263
264 if (udsserver_exit() < 0)
265 LogMsg("ExitCallback: udsserver_exit failed");
266
267 #if MDNS_DEBUGMSGS > 0
268 printf("mDNSResponder exiting normally with %ld\n", err);
269 #endif
270
271 return err;
272 }
273
274 // uds_daemon support ////////////////////////////////////////////////////////////
275
276 #if MDNS_MALLOC_DEBUGGING >= 2
277 #define LogMalloc LogMsg
278 #else
279 #define LogMalloc(ARGS...) ((void)0)
280 #endif
281
282 mStatus udsSupportAddFDToEventLoop(int fd, udsEventCallback callback, void *context)
283 /* Support routine for uds_daemon.c */
284 {
285 // Depends on the fact that udsEventCallback == mDNSPosixEventCallback
286 return mDNSPosixAddFDToEventLoop(fd, callback, context);
287 }
288
289 mStatus udsSupportRemoveFDFromEventLoop(int fd) // Note: This also CLOSES the file descriptor
290 {
291 return mDNSPosixRemoveFDFromEventLoop(fd);
292 close(fd);
293 }
294
295 mDNSexport void RecordUpdatedNiceLabel(mDNS *const m, mDNSs32 delay)
296 {
297 (void)m;
298 (void)delay;
299 // No-op, for now
300 }
301
302 #if MACOSX_MDNS_MALLOC_DEBUGGING >= 1
303
304 void *mallocL(char *msg, unsigned int size)
305 {
306 unsigned long *mem = malloc(size+8);
307 if (!mem)
308 {
309 LogMsg("malloc( %s : %d ) failed", msg, size);
310 return(NULL);
311 }
312 else
313 {
314 LogMalloc("malloc( %s : %lu ) = %p", msg, size, &mem[2]);
315 mem[0] = 0xDEAD1234;
316 mem[1] = size;
317 //bzero(&mem[2], size);
318 memset(&mem[2], 0xFF, size);
319 // validatelists(&mDNSStorage);
320 return(&mem[2]);
321 }
322 }
323
324 void freeL(char *msg, void *x)
325 {
326 if (!x)
327 LogMsg("free( %s @ NULL )!", msg);
328 else
329 {
330 unsigned long *mem = ((unsigned long *)x) - 2;
331 if (mem[0] != 0xDEAD1234)
332 { LogMsg("free( %s @ %p ) !!!! NOT ALLOCATED !!!!", msg, &mem[2]); return; }
333 if (mem[1] > 8000)
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);
339 free(mem);
340 }
341 }
342
343 #endif // MACOSX_MDNS_MALLOC_DEBUGGING >= 1
344
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__ ") ";
348 #else
349 mDNSexport const char mDNSResponderVersionString[] = "mDNSResponder (Engineering Build) (" __DATE__ " " __TIME__ ") ";
350 #endif