1 /* -*- Mode: C; tab-width: 4 -*-
3 * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
19 Contains: main & associated Application layer for mDNSResponder on Linux.
21 Change History (most recent first):
23 $Log: PosixDaemon.c,v $
24 Revision 1.29.2.1 2006/08/29 06:24:34 cheshire
25 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
27 Revision 1.29 2005/08/04 03:37:45 mkrochma
28 Temporary workaround to fix posix after mDNS_SetPrimaryInterfaceInfo changed
30 Revision 1.28 2005/07/19 11:21:09 cheshire
31 <rdar://problem/4170449> Unix Domain Socket leak in mdnsd
33 Revision 1.27 2005/02/04 00:39:59 cheshire
34 Move ParseDNSServers() from PosixDaemon.c to mDNSPosix.c so all Posix client layers can use it
36 Revision 1.26 2005/02/02 02:21:30 cheshire
37 Update references to "mDNSResponder" to say "mdnsd" instead
39 Revision 1.25 2005/01/27 20:01:50 cheshire
40 udsSupportRemoveFDFromEventLoop() needs to close the file descriptor as well
42 Revision 1.24 2005/01/19 19:20:49 ksekar
43 <rdar://problem/3960191> Need a way to turn off domain discovery
45 Revision 1.23 2004/12/16 20:17:11 cheshire
46 <rdar://problem/3324626> Cache memory management improvements
48 Revision 1.22 2004/12/10 13:12:08 cheshire
49 Create no-op function RecordUpdatedNiceLabel(), required by uds_daemon.c
51 Revision 1.21 2004/12/01 20:57:20 ksekar
52 <rdar://problem/3873921> Wide Area Service Discovery must be split-DNS aware
54 Revision 1.20 2004/12/01 04:28:43 cheshire
55 <rdar://problem/3872803> Darwin patches for Solaris and Suse
56 Use version of daemon() provided in mDNSUNP.c instead of local copy
58 Revision 1.19 2004/12/01 03:30:29 cheshire
59 <rdar://problem/3889346> Add Unicast DNS support to mDNSPosix
61 Revision 1.18 2004/11/30 22:45:59 cheshire
64 Revision 1.17 2004/11/30 22:18:59 cheshire
65 <rdar://problem/3889351> Posix needs to read the list of unicast DNS servers and set server list
67 Revision 1.16 2004/09/21 21:05:12 cheshire
68 Move duplicate code out of mDNSMacOSX/daemon.c and mDNSPosix/PosixDaemon.c,
69 into mDNSShared/uds_daemon.c
71 Revision 1.15 2004/09/17 01:08:53 cheshire
72 Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
73 The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
74 declared in that file are ONLY appropriate to single-address-space embedded applications.
75 For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
77 Revision 1.14 2004/09/16 00:24:49 cheshire
78 <rdar://problem/3803162> Fix unsafe use of mDNSPlatformTimeNow()
80 Revision 1.13 2004/08/11 01:59:41 cheshire
81 Remove "mDNS *globalInstance" parameter from udsserver_init()
83 Revision 1.12 2004/06/28 23:19:19 cheshire
84 Fix "Daemon_Init declared but never defined" warning on Linux
86 Revision 1.11 2004/06/25 00:26:27 rpantos
87 Changes to fix the Posix build on Solaris.
89 Revision 1.10 2004/06/08 04:59:40 cheshire
90 Tidy up wording -- log messages are already prefixed with "mDNSResponder", so don't need to repeat it
92 Revision 1.9 2004/05/29 00:14:20 rpantos
93 <rdar://problem/3508093> Runtime check to disable prod mdnsd on OS X.
95 Revision 1.8 2004/04/07 01:19:04 cheshire
96 Hash slot value should be unsigned
98 Revision 1.7 2004/02/14 06:34:57 cheshire
99 Use LogMsg instead of fprintf( stderr
101 Revision 1.6 2004/02/14 01:10:42 rpantos
102 Allow daemon to run if 'nobody' is not defined, with a warning. (For Roku HD1000.)
104 Revision 1.5 2004/02/05 07:45:43 cheshire
107 Revision 1.4 2004/01/28 21:14:23 cheshire
108 Reconcile debug_mode and gDebugLogging into a single flag (mDNS_DebugMode)
110 Revision 1.3 2004/01/19 19:51:46 cheshire
111 Fix compiler error (mixed declarations and code) on some versions of Linux
113 Revision 1.2 2003/12/11 03:03:51 rpantos
114 Clean up mDNSPosix so that it builds on OS X again.
116 Revision 1.1 2003/12/08 20:47:02 rpantos
117 Add support for mDNSResponder on Linux.
128 #include <sys/types.h>
130 #include "mDNSEmbeddedAPI.h"
131 #include "mDNSDebug.h"
132 #include "mDNSPosix.h"
133 #include "uds_daemon.h"
134 #include "PlatformCommon.h"
136 #define CONFIG_FILE "/etc/mdnsd.conf"
137 static domainname DynDNSZone
; // Default wide-area zone for service registration
138 static domainname DynDNSHostname
;
140 #define RR_CACHE_SIZE 500
141 static CacheEntity gRRCache
[RR_CACHE_SIZE
];
143 extern const char mDNSResponderVersionString
[];
145 static void Reconfigure(mDNS
*m
)
148 mDNS_SetPrimaryInterfaceInfo(m
, NULL
, NULL
, NULL
);
149 mDNS_DeleteDNSServers(m
);
150 if (ParseDNSServers(m
, uDNS_SERVERS_FILE
) < 0)
151 LogMsg("Unable to parse DNS server list. Unicast DNS-SD unavailable");
152 ReadDDNSSettingsFromConfFile(m
, CONFIG_FILE
, &DynDNSHostname
, &DynDNSZone
, NULL
);
153 FindDefaultRouteIP(&DynDNSIP
);
154 if (DynDNSHostname
.c
[0]) mDNS_AddDynDNSHostName(m
, &DynDNSHostname
, NULL
, NULL
);
155 if (DynDNSIP
.type
) mDNS_SetPrimaryInterfaceInfo(m
, &DynDNSIP
, NULL
, NULL
);
158 // Do appropriate things at startup with command line arguments. Calls exit() if unhappy.
159 static void ParseCmdLinArgs(int argc
, char **argv
)
163 if (0 == strcmp(argv
[1], "-debug")) mDNS_DebugMode
= mDNStrue
;
164 else printf("Usage: %s [-debug]\n", argv
[0]);
169 int result
= daemon(0, 0);
170 if (result
!= 0) { LogMsg("Could not run as daemon - exiting"); exit(result
); }
172 LogMsg("The POSIX mdnsd should only be used on OS X for testing - exiting");
178 static void DumpStateLog(mDNS
*const m
)
179 // Dump a little log of what we've been up to.
181 LogMsgIdent(mDNSResponderVersionString
, "---- BEGIN STATE LOG ----");
183 LogMsgIdent(mDNSResponderVersionString
, "---- END STATE LOG ----");
186 static mStatus
MainLoop(mDNS
*m
) // Loop until we quit.
189 mDNSBool gotData
= mDNSfalse
;
191 mDNSPosixListenForSignalInEventLoop(SIGINT
);
192 mDNSPosixListenForSignalInEventLoop(SIGTERM
);
193 mDNSPosixListenForSignalInEventLoop(SIGUSR1
);
194 mDNSPosixListenForSignalInEventLoop(SIGPIPE
);
195 mDNSPosixListenForSignalInEventLoop(SIGHUP
) ;
199 // Work out how long we expect to sleep before the next scheduled task
200 struct timeval timeout
;
203 // Only idle if we didn't find any data the last time around
206 mDNSs32 nextTimerEvent
= mDNS_Execute(m
);
207 nextTimerEvent
= udsserver_idle(nextTimerEvent
);
208 ticks
= nextTimerEvent
- mDNS_TimeNow(m
);
209 if (ticks
< 1) ticks
= 1;
211 else // otherwise call EventLoop again with 0 timemout
214 timeout
.tv_sec
= ticks
/ mDNSPlatformOneSecond
;
215 timeout
.tv_usec
= (ticks
% mDNSPlatformOneSecond
) * 1000000 / mDNSPlatformOneSecond
;
217 (void) mDNSPosixRunEventLoopOnce(m
, &timeout
, &signals
, &gotData
);
219 if (sigismember(&signals
, SIGHUP
)) Reconfigure(m
);
220 if (sigismember(&signals
, SIGUSR1
)) DumpStateLog(m
);
221 // SIGPIPE happens when we try to write to a dead client; death should be detected soon in request_callback() and cleaned up.
222 if (sigismember(&signals
, SIGPIPE
)) LogMsg("Received SIGPIPE - ignoring");
223 if (sigismember(&signals
, SIGINT
) || sigismember(&signals
, SIGTERM
)) break;
228 int main(int argc
, char **argv
)
230 #define mDNSRecord mDNSStorage
231 mDNS_PlatformSupport platformStorage
;
234 bzero(&mDNSRecord
, sizeof mDNSRecord
);
235 bzero(&platformStorage
, sizeof platformStorage
);
237 ParseCmdLinArgs(argc
, argv
);
239 LogMsgIdent(mDNSResponderVersionString
, "starting");
241 err
= mDNS_Init(&mDNSRecord
, &platformStorage
, gRRCache
, RR_CACHE_SIZE
, mDNS_Init_AdvertiseLocalAddresses
,
242 mDNS_Init_NoInitCallback
, mDNS_Init_NoInitCallbackContext
);
244 if (mStatus_NoError
== err
)
245 err
= udsserver_init();
247 Reconfigure(&mDNSRecord
);
249 // Now that we're finished with anything privileged, switch over to running as "nobody"
250 if (mStatus_NoError
== err
)
252 const struct passwd
*pw
= getpwnam("nobody");
256 LogMsg("WARNING: mdnsd continuing as root because user \"nobody\" does not exist");
259 if (mStatus_NoError
== err
)
260 err
= MainLoop(&mDNSRecord
);
262 LogMsgIdent(mDNSResponderVersionString
, "stopping");
264 mDNS_Close(&mDNSRecord
);
266 if (udsserver_exit() < 0)
267 LogMsg("ExitCallback: udsserver_exit failed");
269 #if MDNS_DEBUGMSGS > 0
270 printf("mDNSResponder exiting normally with %ld\n", err
);
276 // uds_daemon support ////////////////////////////////////////////////////////////
278 #if MDNS_MALLOC_DEBUGGING >= 2
279 #define LogMalloc LogMsg
281 #define LogMalloc(ARGS...) ((void)0)
284 mStatus
udsSupportAddFDToEventLoop(int fd
, udsEventCallback callback
, void *context
)
285 /* Support routine for uds_daemon.c */
287 // Depends on the fact that udsEventCallback == mDNSPosixEventCallback
288 return mDNSPosixAddFDToEventLoop(fd
, callback
, context
);
291 mStatus
udsSupportRemoveFDFromEventLoop(int fd
) // Note: This also CLOSES the file descriptor
293 mStatus err
= mDNSPosixRemoveFDFromEventLoop(fd
);
298 mDNSexport
void RecordUpdatedNiceLabel(mDNS
*const m
, mDNSs32 delay
)
305 #if MACOSX_MDNS_MALLOC_DEBUGGING >= 1
307 void *mallocL(char *msg
, unsigned int size
)
309 unsigned long *mem
= malloc(size
+8);
312 LogMsg("malloc( %s : %d ) failed", msg
, size
);
317 LogMalloc("malloc( %s : %lu ) = %p", msg
, size
, &mem
[2]);
320 //bzero(&mem[2], size);
321 memset(&mem
[2], 0xFF, size
);
322 // validatelists(&mDNSStorage);
327 void freeL(char *msg
, void *x
)
330 LogMsg("free( %s @ NULL )!", msg
);
333 unsigned long *mem
= ((unsigned long *)x
) - 2;
334 if (mem
[0] != 0xDEAD1234)
335 { LogMsg("free( %s @ %p ) !!!! NOT ALLOCATED !!!!", msg
, &mem
[2]); return; }
337 { LogMsg("free( %s : %ld @ %p) too big!", msg
, mem
[1], &mem
[2]); return; }
338 LogMalloc("free( %s : %ld @ %p)", msg
, mem
[1], &mem
[2]);
339 //bzero(mem, mem[1]+8);
340 memset(mem
, 0xDD, mem
[1]+8);
341 // validatelists(&mDNSStorage);
346 #endif // MACOSX_MDNS_MALLOC_DEBUGGING >= 1
348 // For convenience when using the "strings" command, this is the last thing in the file
349 #if mDNSResponderVersion > 1
350 mDNSexport
const char mDNSResponderVersionString
[] = "mDNSResponder-" STRINGIFY(mDNSResponderVersion
) " (" __DATE__
" " __TIME__
") ";
352 mDNSexport
const char mDNSResponderVersionString
[] = "mDNSResponder (Engineering Build) (" __DATE__
" " __TIME__
") ";