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.29 2005/08/04 03:37:45 mkrochma
32 Temporary workaround to fix posix after mDNS_SetPrimaryInterfaceInfo changed
34 Revision 1.28 2005/07/19 11:21:09 cheshire
35 <rdar://problem/4170449> Unix Domain Socket leak in mdnsd
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
40 Revision 1.26 2005/02/02 02:21:30 cheshire
41 Update references to "mDNSResponder" to say "mdnsd" instead
43 Revision 1.25 2005/01/27 20:01:50 cheshire
44 udsSupportRemoveFDFromEventLoop() needs to close the file descriptor as well
46 Revision 1.24 2005/01/19 19:20:49 ksekar
47 <rdar://problem/3960191> Need a way to turn off domain discovery
49 Revision 1.23 2004/12/16 20:17:11 cheshire
50 <rdar://problem/3324626> Cache memory management improvements
52 Revision 1.22 2004/12/10 13:12:08 cheshire
53 Create no-op function RecordUpdatedNiceLabel(), required by uds_daemon.c
55 Revision 1.21 2004/12/01 20:57:20 ksekar
56 <rdar://problem/3873921> Wide Area Service Discovery must be split-DNS aware
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
62 Revision 1.19 2004/12/01 03:30:29 cheshire
63 <rdar://problem/3889346> Add Unicast DNS support to mDNSPosix
65 Revision 1.18 2004/11/30 22:45:59 cheshire
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
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
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.
81 Revision 1.14 2004/09/16 00:24:49 cheshire
82 <rdar://problem/3803162> Fix unsafe use of mDNSPlatformTimeNow()
84 Revision 1.13 2004/08/11 01:59:41 cheshire
85 Remove "mDNS *globalInstance" parameter from udsserver_init()
87 Revision 1.12 2004/06/28 23:19:19 cheshire
88 Fix "Daemon_Init declared but never defined" warning on Linux
90 Revision 1.11 2004/06/25 00:26:27 rpantos
91 Changes to fix the Posix build on Solaris.
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
96 Revision 1.9 2004/05/29 00:14:20 rpantos
97 <rdar://problem/3508093> Runtime check to disable prod mdnsd on OS X.
99 Revision 1.8 2004/04/07 01:19:04 cheshire
100 Hash slot value should be unsigned
102 Revision 1.7 2004/02/14 06:34:57 cheshire
103 Use LogMsg instead of fprintf( stderr
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.)
108 Revision 1.5 2004/02/05 07:45:43 cheshire
111 Revision 1.4 2004/01/28 21:14:23 cheshire
112 Reconcile debug_mode and gDebugLogging into a single flag (mDNS_DebugMode)
114 Revision 1.3 2004/01/19 19:51:46 cheshire
115 Fix compiler error (mixed declarations and code) on some versions of Linux
117 Revision 1.2 2003/12/11 03:03:51 rpantos
118 Clean up mDNSPosix so that it builds on OS X again.
120 Revision 1.1 2003/12/08 20:47:02 rpantos
121 Add support for mDNSResponder on Linux.
132 #include <sys/types.h>
134 #include "mDNSEmbeddedAPI.h"
135 #include "mDNSDebug.h"
136 #include "mDNSPosix.h"
137 #include "uds_daemon.h"
138 #include "PlatformCommon.h"
140 #define CONFIG_FILE "/etc/mdnsd.conf"
141 static domainname DynDNSZone
; // Default wide-area zone for service registration
142 static domainname DynDNSHostname
;
144 #define RR_CACHE_SIZE 500
145 static CacheEntity gRRCache
[RR_CACHE_SIZE
];
147 extern const char mDNSResponderVersionString
[];
149 static void Reconfigure(mDNS
*m
)
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
);
162 // Do appropriate things at startup with command line arguments. Calls exit() if unhappy.
163 static void ParseCmdLinArgs(int argc
, char **argv
)
167 if (0 == strcmp(argv
[1], "-debug")) mDNS_DebugMode
= mDNStrue
;
168 else printf("Usage: %s [-debug]\n", argv
[0]);
173 int result
= daemon(0, 0);
174 if (result
!= 0) { LogMsg("Could not run as daemon - exiting"); exit(result
); }
176 LogMsg("The POSIX mdnsd should only be used on OS X for testing - exiting");
182 static void DumpStateLog(mDNS
*const m
)
183 // Dump a little log of what we've been up to.
185 LogMsgIdent(mDNSResponderVersionString
, "---- BEGIN STATE LOG ----");
187 LogMsgIdent(mDNSResponderVersionString
, "---- END STATE LOG ----");
190 static mStatus
MainLoop(mDNS
*m
) // Loop until we quit.
193 mDNSBool gotData
= mDNSfalse
;
195 mDNSPosixListenForSignalInEventLoop(SIGINT
);
196 mDNSPosixListenForSignalInEventLoop(SIGTERM
);
197 mDNSPosixListenForSignalInEventLoop(SIGUSR1
);
198 mDNSPosixListenForSignalInEventLoop(SIGPIPE
);
199 mDNSPosixListenForSignalInEventLoop(SIGHUP
) ;
203 // Work out how long we expect to sleep before the next scheduled task
204 struct timeval timeout
;
207 // Only idle if we didn't find any data the last time around
210 mDNSs32 nextTimerEvent
= mDNS_Execute(m
);
211 nextTimerEvent
= udsserver_idle(nextTimerEvent
);
212 ticks
= nextTimerEvent
- mDNS_TimeNow(m
);
213 if (ticks
< 1) ticks
= 1;
215 else // otherwise call EventLoop again with 0 timemout
218 timeout
.tv_sec
= ticks
/ mDNSPlatformOneSecond
;
219 timeout
.tv_usec
= (ticks
% mDNSPlatformOneSecond
) * 1000000 / mDNSPlatformOneSecond
;
221 (void) mDNSPosixRunEventLoopOnce(m
, &timeout
, &signals
, &gotData
);
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;
232 int main(int argc
, char **argv
)
234 #define mDNSRecord mDNSStorage
235 mDNS_PlatformSupport platformStorage
;
238 bzero(&mDNSRecord
, sizeof mDNSRecord
);
239 bzero(&platformStorage
, sizeof platformStorage
);
241 ParseCmdLinArgs(argc
, argv
);
243 LogMsgIdent(mDNSResponderVersionString
, "starting");
245 err
= mDNS_Init(&mDNSRecord
, &platformStorage
, gRRCache
, RR_CACHE_SIZE
, mDNS_Init_AdvertiseLocalAddresses
,
246 mDNS_Init_NoInitCallback
, mDNS_Init_NoInitCallbackContext
);
248 if (mStatus_NoError
== err
)
249 err
= udsserver_init();
251 Reconfigure(&mDNSRecord
);
253 // Now that we're finished with anything privileged, switch over to running as "nobody"
254 if (mStatus_NoError
== err
)
256 const struct passwd
*pw
= getpwnam("nobody");
260 LogMsg("WARNING: mdnsd continuing as root because user \"nobody\" does not exist");
263 if (mStatus_NoError
== err
)
264 err
= MainLoop(&mDNSRecord
);
266 LogMsgIdent(mDNSResponderVersionString
, "stopping");
268 mDNS_Close(&mDNSRecord
);
270 if (udsserver_exit() < 0)
271 LogMsg("ExitCallback: udsserver_exit failed");
273 #if MDNS_DEBUGMSGS > 0
274 printf("mDNSResponder exiting normally with %ld\n", err
);
280 // uds_daemon support ////////////////////////////////////////////////////////////
282 #if MDNS_MALLOC_DEBUGGING >= 2
283 #define LogMalloc LogMsg
285 #define LogMalloc(ARGS...) ((void)0)
288 mStatus
udsSupportAddFDToEventLoop(int fd
, udsEventCallback callback
, void *context
)
289 /* Support routine for uds_daemon.c */
291 // Depends on the fact that udsEventCallback == mDNSPosixEventCallback
292 return mDNSPosixAddFDToEventLoop(fd
, callback
, context
);
295 mStatus
udsSupportRemoveFDFromEventLoop(int fd
) // Note: This also CLOSES the file descriptor
297 mStatus err
= mDNSPosixRemoveFDFromEventLoop(fd
);
302 mDNSexport
void RecordUpdatedNiceLabel(mDNS
*const m
, mDNSs32 delay
)
309 #if MACOSX_MDNS_MALLOC_DEBUGGING >= 1
311 void *mallocL(char *msg
, unsigned int size
)
313 unsigned long *mem
= malloc(size
+8);
316 LogMsg("malloc( %s : %d ) failed", msg
, size
);
321 LogMalloc("malloc( %s : %lu ) = %p", msg
, size
, &mem
[2]);
324 //bzero(&mem[2], size);
325 memset(&mem
[2], 0xFF, size
);
326 // validatelists(&mDNSStorage);
331 void freeL(char *msg
, void *x
)
334 LogMsg("free( %s @ NULL )!", msg
);
337 unsigned long *mem
= ((unsigned long *)x
) - 2;
338 if (mem
[0] != 0xDEAD1234)
339 { LogMsg("free( %s @ %p ) !!!! NOT ALLOCATED !!!!", msg
, &mem
[2]); return; }
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);
350 #endif // MACOSX_MDNS_MALLOC_DEBUGGING >= 1
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__
") ";
356 mDNSexport
const char mDNSResponderVersionString
[] = "mDNSResponder (Engineering Build) (" __DATE__
" " __TIME__
") ";