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.22 2004/12/10 13:12:08 cheshire
32 Create no-op function RecordUpdatedNiceLabel(), required by uds_daemon.c
34 Revision 1.21 2004/12/01 20:57:20 ksekar
35 <rdar://problem/3873921> Wide Area Rendezvous must be split-DNS aware
37 Revision 1.20 2004/12/01 04:28:43 cheshire
38 <rdar://problem/3872803> Darwin patches for Solaris and Suse
39 Use version of daemon() provided in mDNSUNP.c instead of local copy
41 Revision 1.19 2004/12/01 03:30:29 cheshire
42 <rdar://problem/3889346> Add Unicast DNS support to mDNSPosix
44 Revision 1.18 2004/11/30 22:45:59 cheshire
47 Revision 1.17 2004/11/30 22:18:59 cheshire
48 <rdar://problem/3889351> Posix needs to read the list of unicast DNS servers and set server list
50 Revision 1.16 2004/09/21 21:05:12 cheshire
51 Move duplicate code out of mDNSMacOSX/daemon.c and mDNSPosix/PosixDaemon.c,
52 into mDNSShared/uds_daemon.c
54 Revision 1.15 2004/09/17 01:08:53 cheshire
55 Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
56 The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
57 declared in that file are ONLY appropriate to single-address-space embedded applications.
58 For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
60 Revision 1.14 2004/09/16 00:24:49 cheshire
61 <rdar://problem/3803162> Fix unsafe use of mDNSPlatformTimeNow()
63 Revision 1.13 2004/08/11 01:59:41 cheshire
64 Remove "mDNS *globalInstance" parameter from udsserver_init()
66 Revision 1.12 2004/06/28 23:19:19 cheshire
67 Fix "Daemon_Init declared but never defined" warning on Linux
69 Revision 1.11 2004/06/25 00:26:27 rpantos
70 Changes to fix the Posix build on Solaris.
72 Revision 1.10 2004/06/08 04:59:40 cheshire
73 Tidy up wording -- log messages are already prefixed with "mDNSResponder", so don't need to repeat it
75 Revision 1.9 2004/05/29 00:14:20 rpantos
76 <rdar://problem/3508093> Runtime check to disable prod mdnsd on OS X.
78 Revision 1.8 2004/04/07 01:19:04 cheshire
79 Hash slot value should be unsigned
81 Revision 1.7 2004/02/14 06:34:57 cheshire
82 Use LogMsg instead of fprintf( stderr
84 Revision 1.6 2004/02/14 01:10:42 rpantos
85 Allow daemon to run if 'nobody' is not defined, with a warning. (For Roku HD1000.)
87 Revision 1.5 2004/02/05 07:45:43 cheshire
90 Revision 1.4 2004/01/28 21:14:23 cheshire
91 Reconcile debug_mode and gDebugLogging into a single flag (mDNS_DebugMode)
93 Revision 1.3 2004/01/19 19:51:46 cheshire
94 Fix compiler error (mixed declarations and code) on some versions of Linux
96 Revision 1.2 2003/12/11 03:03:51 rpantos
97 Clean up mDNSPosix so that it builds on OS X again.
99 Revision 1.1 2003/12/08 20:47:02 rpantos
100 Add support for mDNSResponder on Linux.
111 #include <sys/types.h>
112 #include <netinet/in.h>
113 #include <arpa/inet.h>
115 #include "mDNSEmbeddedAPI.h"
116 #include "mDNSDebug.h"
117 #include "mDNSPosix.h"
118 #include "uds_daemon.h"
119 #include "PlatformCommon.h"
121 #define uDNS_SERVERS_FILE "/etc/resolv.conf"
123 #define CONFIG_FILE "/etc/mdnsd.conf"
124 static domainname DynDNSZone
; // Default wide-area zone for service registration
125 static domainname DynDNSHostname
;
127 #define RR_CACHE_SIZE 500
128 static CacheRecord gRRCache
[RR_CACHE_SIZE
];
130 extern const char mDNSResponderVersionString
[];
132 static int ParseDNSServers(mDNS
*m
, const char *filePath
)
137 int numOfServers
= 0;
138 FILE *fp
= fopen(filePath
, "r");
139 if (fp
== NULL
) return -1;
140 while (fgets(line
,sizeof(line
),fp
))
143 line
[255]='\0'; // just to be safe
144 if (sscanf(line
,"%10s %15s", keyword
, nameserver
) != 2) continue; // it will skip whitespaces
145 if (strncmp(keyword
,"nameserver",10)) continue;
146 if (inet_aton(nameserver
, (struct in_addr
*)&ina
) != 0)
149 DNSAddr
.type
= mDNSAddrType_IPv4
;
150 DNSAddr
.ip
.v4
.NotAnInteger
= ina
.s_addr
;
151 mDNS_AddDNSServer(m
, &DNSAddr
, NULL
);
155 return (numOfServers
> 0) ? 0 : -1;
158 static void Reconfigure(mDNS
*m
)
161 mDNS_SetPrimaryInterfaceInfo(m
, NULL
, NULL
);
162 mDNS_DeleteDNSServers(m
);
163 if (ParseDNSServers(m
, uDNS_SERVERS_FILE
) < 0)
164 LogMsg("Unable to parse DNS server list. Unicast DNS-SD unavailable");
165 ReadDDNSSettingsFromConfFile(m
, CONFIG_FILE
, &DynDNSHostname
, &DynDNSZone
);
166 FindDefaultRouteIP(&DynDNSIP
);
167 if (DynDNSHostname
.c
[0]) mDNS_AddDynDNSHostName(m
, &DynDNSHostname
, NULL
, NULL
);
168 if (DynDNSIP
.type
) mDNS_SetPrimaryInterfaceInfo(m
, &DynDNSIP
, NULL
);
171 // Do appropriate things at startup with command line arguments. Calls exit() if unhappy.
172 static void ParseCmdLinArgs(int argc
, char **argv
)
176 if (0 == strcmp(argv
[1], "-debug")) mDNS_DebugMode
= mDNStrue
;
177 else printf("Usage: mDNSResponder [-debug]\n");
182 int result
= daemon(0, 0);
183 if (result
!= 0) { LogMsg("Could not run as daemon - exiting"); exit(result
); }
185 LogMsg("The POSIX mDNSResponder should only be used on OS X for testing - exiting");
191 static void DumpStateLog(mDNS
*const m
)
192 // Dump a little log of what we've been up to.
194 LogMsgIdent(mDNSResponderVersionString
, "---- BEGIN STATE LOG ----");
196 LogMsgIdent(mDNSResponderVersionString
, "---- END STATE LOG ----");
199 static mStatus
MainLoop(mDNS
*m
) // Loop until we quit.
202 mDNSBool gotData
= mDNSfalse
;
204 mDNSPosixListenForSignalInEventLoop(SIGINT
);
205 mDNSPosixListenForSignalInEventLoop(SIGTERM
);
206 mDNSPosixListenForSignalInEventLoop(SIGUSR1
);
207 mDNSPosixListenForSignalInEventLoop(SIGPIPE
);
208 mDNSPosixListenForSignalInEventLoop(SIGHUP
) ;
212 // Work out how long we expect to sleep before the next scheduled task
213 struct timeval timeout
;
216 // Only idle if we didn't find any data the last time around
219 mDNSs32 nextTimerEvent
= mDNS_Execute(m
);
220 nextTimerEvent
= udsserver_idle(nextTimerEvent
);
221 ticks
= nextTimerEvent
- mDNS_TimeNow(m
);
222 if (ticks
< 1) ticks
= 1;
224 else // otherwise call EventLoop again with 0 timemout
227 timeout
.tv_sec
= ticks
/ mDNSPlatformOneSecond
;
228 timeout
.tv_usec
= (ticks
% mDNSPlatformOneSecond
) * 1000000 / mDNSPlatformOneSecond
;
230 (void) mDNSPosixRunEventLoopOnce(m
, &timeout
, &signals
, &gotData
);
232 if (sigismember(&signals
, SIGHUP
)) Reconfigure(m
);
233 if (sigismember(&signals
, SIGUSR1
)) DumpStateLog(m
);
234 // SIGPIPE happens when we try to write to a dead client; death should be detected soon in request_callback() and cleaned up.
235 if (sigismember(&signals
, SIGPIPE
)) LogMsg("Received SIGPIPE - ignoring");
236 if (sigismember(&signals
, SIGINT
) || sigismember(&signals
, SIGTERM
)) break;
241 int main(int argc
, char **argv
)
243 #define mDNSRecord mDNSStorage
244 mDNS_PlatformSupport platformStorage
;
247 bzero(&mDNSRecord
, sizeof mDNSRecord
);
248 bzero(&platformStorage
, sizeof platformStorage
);
250 ParseCmdLinArgs(argc
, argv
);
252 err
= mDNS_Init(&mDNSRecord
, &platformStorage
, gRRCache
, RR_CACHE_SIZE
, mDNS_Init_AdvertiseLocalAddresses
,
253 mDNS_Init_NoInitCallback
, mDNS_Init_NoInitCallbackContext
);
255 if (mStatus_NoError
== err
)
256 err
= udsserver_init();
258 Reconfigure(&mDNSRecord
);
260 // Now that we're finished with anything privileged, switch over to running as "nobody"
261 if (mStatus_NoError
== err
)
263 const struct passwd
*pw
= getpwnam("nobody");
267 LogMsg("WARNING: mdnsd continuing as root because user \"nobody\" does not exist");
270 if (mStatus_NoError
== err
)
271 err
= MainLoop(&mDNSRecord
);
273 mDNS_Close(&mDNSRecord
);
275 if (udsserver_exit() < 0)
276 LogMsg("ExitCallback: udsserver_exit failed");
278 #if MDNS_DEBUGMSGS > 0
279 printf("mDNSResponder exiting normally with %ld\n", err
);
285 // uds_daemon support ////////////////////////////////////////////////////////////
287 #if MDNS_MALLOC_DEBUGGING >= 2
288 #define LogMalloc LogMsg
290 #define LogMalloc(ARGS...) ((void)0)
293 mStatus
udsSupportAddFDToEventLoop(int fd
, udsEventCallback callback
, void *context
)
294 /* Support routine for uds_daemon.c */
296 // Depends on the fact that udsEventCallback == mDNSPosixEventCallback
297 return mDNSPosixAddFDToEventLoop(fd
, callback
, context
);
300 mStatus
udsSupportRemoveFDFromEventLoop(int fd
)
302 return mDNSPosixRemoveFDFromEventLoop(fd
);
305 mDNSexport
void RecordUpdatedNiceLabel(mDNS
*const m
, mDNSs32 delay
)
312 #if MACOSX_MDNS_MALLOC_DEBUGGING >= 1
314 void *mallocL(char *msg
, unsigned int size
)
316 unsigned long *mem
= malloc(size
+8);
319 LogMsg("malloc( %s : %d ) failed", msg
, size
);
324 LogMalloc("malloc( %s : %lu ) = %p", msg
, size
, &mem
[2]);
327 //bzero(&mem[2], size);
328 memset(&mem
[2], 0xFF, size
);
329 // validatelists(&mDNSStorage);
334 void freeL(char *msg
, void *x
)
337 LogMsg("free( %s @ NULL )!", msg
);
340 unsigned long *mem
= ((unsigned long *)x
) - 2;
341 if (mem
[0] != 0xDEAD1234)
342 { LogMsg("free( %s @ %p ) !!!! NOT ALLOCATED !!!!", msg
, &mem
[2]); return; }
344 { LogMsg("free( %s : %ld @ %p) too big!", msg
, mem
[1], &mem
[2]); return; }
345 LogMalloc("free( %s : %ld @ %p)", msg
, mem
[1], &mem
[2]);
346 //bzero(mem, mem[1]+8);
347 memset(mem
, 0xDD, mem
[1]+8);
348 // validatelists(&mDNSStorage);
353 #endif // MACOSX_MDNS_MALLOC_DEBUGGING >= 1
355 // For convenience when using the "strings" command, this is the last thing in the file
356 #if mDNSResponderVersion > 1
357 mDNSexport
const char mDNSResponderVersionString
[] = "mDNSResponder-" STRINGIFY(mDNSResponderVersion
) " (" __DATE__
" " __TIME__
") ";
359 mDNSexport
const char mDNSResponderVersionString
[] = "mDNSResponder (Engineering Build) (" __DATE__
" " __TIME__
") ";