]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSPosix/PosixDaemon.c
mDNSResponder-108.4.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.29 2005/08/04 03:37:45 mkrochma
32 Temporary workaround to fix posix after mDNS_SetPrimaryInterfaceInfo changed
33
34 Revision 1.28 2005/07/19 11:21:09 cheshire
35 <rdar://problem/4170449> Unix Domain Socket leak in mdnsd
36
37 Revision 1.27 2005/02/04 00:39:59 cheshire
38 Move ParseDNSServers() from PosixDaemon.c to mDNSPosix.c so all Posix client layers can use it
39
40 Revision 1.26 2005/02/02 02:21:30 cheshire
41 Update references to "mDNSResponder" to say "mdnsd" instead
42
43 Revision 1.25 2005/01/27 20:01:50 cheshire
44 udsSupportRemoveFDFromEventLoop() needs to close the file descriptor as well
45
46 Revision 1.24 2005/01/19 19:20:49 ksekar
47 <rdar://problem/3960191> Need a way to turn off domain discovery
48
49 Revision 1.23 2004/12/16 20:17:11 cheshire
50 <rdar://problem/3324626> Cache memory management improvements
51
52 Revision 1.22 2004/12/10 13:12:08 cheshire
53 Create no-op function RecordUpdatedNiceLabel(), required by uds_daemon.c
54
55 Revision 1.21 2004/12/01 20:57:20 ksekar
56 <rdar://problem/3873921> Wide Area Service Discovery must be split-DNS aware
57
58 Revision 1.20 2004/12/01 04:28:43 cheshire
59 <rdar://problem/3872803> Darwin patches for Solaris and Suse
60 Use version of daemon() provided in mDNSUNP.c instead of local copy
61
62 Revision 1.19 2004/12/01 03:30:29 cheshire
63 <rdar://problem/3889346> Add Unicast DNS support to mDNSPosix
64
65 Revision 1.18 2004/11/30 22:45:59 cheshire
66 Minor code tidying
67
68 Revision 1.17 2004/11/30 22:18:59 cheshire
69 <rdar://problem/3889351> Posix needs to read the list of unicast DNS servers and set server list
70
71 Revision 1.16 2004/09/21 21:05:12 cheshire
72 Move duplicate code out of mDNSMacOSX/daemon.c and mDNSPosix/PosixDaemon.c,
73 into mDNSShared/uds_daemon.c
74
75 Revision 1.15 2004/09/17 01:08:53 cheshire
76 Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
77 The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
78 declared in that file are ONLY appropriate to single-address-space embedded applications.
79 For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
80
81 Revision 1.14 2004/09/16 00:24:49 cheshire
82 <rdar://problem/3803162> Fix unsafe use of mDNSPlatformTimeNow()
83
84 Revision 1.13 2004/08/11 01:59:41 cheshire
85 Remove "mDNS *globalInstance" parameter from udsserver_init()
86
87 Revision 1.12 2004/06/28 23:19:19 cheshire
88 Fix "Daemon_Init declared but never defined" warning on Linux
89
90 Revision 1.11 2004/06/25 00:26:27 rpantos
91 Changes to fix the Posix build on Solaris.
92
93 Revision 1.10 2004/06/08 04:59:40 cheshire
94 Tidy up wording -- log messages are already prefixed with "mDNSResponder", so don't need to repeat it
95
96 Revision 1.9 2004/05/29 00:14:20 rpantos
97 <rdar://problem/3508093> Runtime check to disable prod mdnsd on OS X.
98
99 Revision 1.8 2004/04/07 01:19:04 cheshire
100 Hash slot value should be unsigned
101
102 Revision 1.7 2004/02/14 06:34:57 cheshire
103 Use LogMsg instead of fprintf( stderr
104
105 Revision 1.6 2004/02/14 01:10:42 rpantos
106 Allow daemon to run if 'nobody' is not defined, with a warning. (For Roku HD1000.)
107
108 Revision 1.5 2004/02/05 07:45:43 cheshire
109 Add Log header
110
111 Revision 1.4 2004/01/28 21:14:23 cheshire
112 Reconcile debug_mode and gDebugLogging into a single flag (mDNS_DebugMode)
113
114 Revision 1.3 2004/01/19 19:51:46 cheshire
115 Fix compiler error (mixed declarations and code) on some versions of Linux
116
117 Revision 1.2 2003/12/11 03:03:51 rpantos
118 Clean up mDNSPosix so that it builds on OS X again.
119
120 Revision 1.1 2003/12/08 20:47:02 rpantos
121 Add support for mDNSResponder on Linux.
122 */
123
124 #include <stdio.h>
125 #include <string.h>
126 #include <unistd.h>
127 #include <stdlib.h>
128 #include <signal.h>
129 #include <errno.h>
130 #include <fcntl.h>
131 #include <pwd.h>
132 #include <sys/types.h>
133
134 #include "mDNSEmbeddedAPI.h"
135 #include "mDNSDebug.h"
136 #include "mDNSPosix.h"
137 #include "uds_daemon.h"
138 #include "PlatformCommon.h"
139
140 #define CONFIG_FILE "/etc/mdnsd.conf"
141 static domainname DynDNSZone; // Default wide-area zone for service registration
142 static domainname DynDNSHostname;
143
144 #define RR_CACHE_SIZE 500
145 static CacheEntity gRRCache[RR_CACHE_SIZE];
146
147 extern const char mDNSResponderVersionString[];
148
149 static void Reconfigure(mDNS *m)
150 {
151 mDNSAddr DynDNSIP;
152 mDNS_SetPrimaryInterfaceInfo(m, NULL, NULL, NULL);
153 mDNS_DeleteDNSServers(m);
154 if (ParseDNSServers(m, uDNS_SERVERS_FILE) < 0)
155 LogMsg("Unable to parse DNS server list. Unicast DNS-SD unavailable");
156 ReadDDNSSettingsFromConfFile(m, CONFIG_FILE, &DynDNSHostname, &DynDNSZone, NULL);
157 FindDefaultRouteIP(&DynDNSIP);
158 if (DynDNSHostname.c[0]) mDNS_AddDynDNSHostName(m, &DynDNSHostname, NULL, NULL);
159 if (DynDNSIP.type) mDNS_SetPrimaryInterfaceInfo(m, &DynDNSIP, NULL, NULL);
160 }
161
162 // Do appropriate things at startup with command line arguments. Calls exit() if unhappy.
163 static void ParseCmdLinArgs(int argc, char **argv)
164 {
165 if (argc > 1)
166 {
167 if (0 == strcmp(argv[1], "-debug")) mDNS_DebugMode = mDNStrue;
168 else printf("Usage: %s [-debug]\n", argv[0]);
169 }
170
171 if (!mDNS_DebugMode)
172 {
173 int result = daemon(0, 0);
174 if (result != 0) { LogMsg("Could not run as daemon - exiting"); exit(result); }
175 #if __APPLE__
176 LogMsg("The POSIX mdnsd should only be used on OS X for testing - exiting");
177 exit(-1);
178 #endif
179 }
180 }
181
182 static void DumpStateLog(mDNS *const m)
183 // Dump a little log of what we've been up to.
184 {
185 LogMsgIdent(mDNSResponderVersionString, "---- BEGIN STATE LOG ----");
186 udsserver_info(m);
187 LogMsgIdent(mDNSResponderVersionString, "---- END STATE LOG ----");
188 }
189
190 static mStatus MainLoop(mDNS *m) // Loop until we quit.
191 {
192 sigset_t signals;
193 mDNSBool gotData = mDNSfalse;
194
195 mDNSPosixListenForSignalInEventLoop(SIGINT);
196 mDNSPosixListenForSignalInEventLoop(SIGTERM);
197 mDNSPosixListenForSignalInEventLoop(SIGUSR1);
198 mDNSPosixListenForSignalInEventLoop(SIGPIPE);
199 mDNSPosixListenForSignalInEventLoop(SIGHUP) ;
200
201 for (; ;)
202 {
203 // Work out how long we expect to sleep before the next scheduled task
204 struct timeval timeout;
205 mDNSs32 ticks;
206
207 // Only idle if we didn't find any data the last time around
208 if (!gotData)
209 {
210 mDNSs32 nextTimerEvent = mDNS_Execute(m);
211 nextTimerEvent = udsserver_idle(nextTimerEvent);
212 ticks = nextTimerEvent - mDNS_TimeNow(m);
213 if (ticks < 1) ticks = 1;
214 }
215 else // otherwise call EventLoop again with 0 timemout
216 ticks = 0;
217
218 timeout.tv_sec = ticks / mDNSPlatformOneSecond;
219 timeout.tv_usec = (ticks % mDNSPlatformOneSecond) * 1000000 / mDNSPlatformOneSecond;
220
221 (void) mDNSPosixRunEventLoopOnce(m, &timeout, &signals, &gotData);
222
223 if (sigismember(&signals, SIGHUP )) Reconfigure(m);
224 if (sigismember(&signals, SIGUSR1)) DumpStateLog(m);
225 // SIGPIPE happens when we try to write to a dead client; death should be detected soon in request_callback() and cleaned up.
226 if (sigismember(&signals, SIGPIPE)) LogMsg("Received SIGPIPE - ignoring");
227 if (sigismember(&signals, SIGINT) || sigismember(&signals, SIGTERM)) break;
228 }
229 return EINTR;
230 }
231
232 int main(int argc, char **argv)
233 {
234 #define mDNSRecord mDNSStorage
235 mDNS_PlatformSupport platformStorage;
236 mStatus err;
237
238 bzero(&mDNSRecord, sizeof mDNSRecord);
239 bzero(&platformStorage, sizeof platformStorage);
240
241 ParseCmdLinArgs(argc, argv);
242
243 LogMsgIdent(mDNSResponderVersionString, "starting");
244
245 err = mDNS_Init(&mDNSRecord, &platformStorage, gRRCache, RR_CACHE_SIZE, mDNS_Init_AdvertiseLocalAddresses,
246 mDNS_Init_NoInitCallback, mDNS_Init_NoInitCallbackContext);
247
248 if (mStatus_NoError == err)
249 err = udsserver_init();
250
251 Reconfigure(&mDNSRecord);
252
253 // Now that we're finished with anything privileged, switch over to running as "nobody"
254 if (mStatus_NoError == err)
255 {
256 const struct passwd *pw = getpwnam("nobody");
257 if (pw != NULL)
258 setuid(pw->pw_uid);
259 else
260 LogMsg("WARNING: mdnsd continuing as root because user \"nobody\" does not exist");
261 }
262
263 if (mStatus_NoError == err)
264 err = MainLoop(&mDNSRecord);
265
266 LogMsgIdent(mDNSResponderVersionString, "stopping");
267
268 mDNS_Close(&mDNSRecord);
269
270 if (udsserver_exit() < 0)
271 LogMsg("ExitCallback: udsserver_exit failed");
272
273 #if MDNS_DEBUGMSGS > 0
274 printf("mDNSResponder exiting normally with %ld\n", err);
275 #endif
276
277 return err;
278 }
279
280 // uds_daemon support ////////////////////////////////////////////////////////////
281
282 #if MDNS_MALLOC_DEBUGGING >= 2
283 #define LogMalloc LogMsg
284 #else
285 #define LogMalloc(ARGS...) ((void)0)
286 #endif
287
288 mStatus udsSupportAddFDToEventLoop(int fd, udsEventCallback callback, void *context)
289 /* Support routine for uds_daemon.c */
290 {
291 // Depends on the fact that udsEventCallback == mDNSPosixEventCallback
292 return mDNSPosixAddFDToEventLoop(fd, callback, context);
293 }
294
295 mStatus udsSupportRemoveFDFromEventLoop(int fd) // Note: This also CLOSES the file descriptor
296 {
297 mStatus err = mDNSPosixRemoveFDFromEventLoop(fd);
298 close(fd);
299 return err;
300 }
301
302 mDNSexport void RecordUpdatedNiceLabel(mDNS *const m, mDNSs32 delay)
303 {
304 (void)m;
305 (void)delay;
306 // No-op, for now
307 }
308
309 #if MACOSX_MDNS_MALLOC_DEBUGGING >= 1
310
311 void *mallocL(char *msg, unsigned int size)
312 {
313 unsigned long *mem = malloc(size+8);
314 if (!mem)
315 {
316 LogMsg("malloc( %s : %d ) failed", msg, size);
317 return(NULL);
318 }
319 else
320 {
321 LogMalloc("malloc( %s : %lu ) = %p", msg, size, &mem[2]);
322 mem[0] = 0xDEAD1234;
323 mem[1] = size;
324 //bzero(&mem[2], size);
325 memset(&mem[2], 0xFF, size);
326 // validatelists(&mDNSStorage);
327 return(&mem[2]);
328 }
329 }
330
331 void freeL(char *msg, void *x)
332 {
333 if (!x)
334 LogMsg("free( %s @ NULL )!", msg);
335 else
336 {
337 unsigned long *mem = ((unsigned long *)x) - 2;
338 if (mem[0] != 0xDEAD1234)
339 { LogMsg("free( %s @ %p ) !!!! NOT ALLOCATED !!!!", msg, &mem[2]); return; }
340 if (mem[1] > 8000)
341 { LogMsg("free( %s : %ld @ %p) too big!", msg, mem[1], &mem[2]); return; }
342 LogMalloc("free( %s : %ld @ %p)", msg, mem[1], &mem[2]);
343 //bzero(mem, mem[1]+8);
344 memset(mem, 0xDD, mem[1]+8);
345 // validatelists(&mDNSStorage);
346 free(mem);
347 }
348 }
349
350 #endif // MACOSX_MDNS_MALLOC_DEBUGGING >= 1
351
352 // For convenience when using the "strings" command, this is the last thing in the file
353 #if mDNSResponderVersion > 1
354 mDNSexport const char mDNSResponderVersionString[] = "mDNSResponder-" STRINGIFY(mDNSResponderVersion) " (" __DATE__ " " __TIME__ ") ";
355 #else
356 mDNSexport const char mDNSResponderVersionString[] = "mDNSResponder (Engineering Build) (" __DATE__ " " __TIME__ ") ";
357 #endif