2 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
27 Contains: main & associated Application layer for mDNSResponder on Linux.
32 Change History (most recent first):
34 $Log: PosixDaemon.c,v $
35 Revision 1.10 2004/06/08 04:59:40 cheshire
36 Tidy up wording -- log messages are already prefixed with "mDNSResponder", so don't need to repeat it
38 Revision 1.9 2004/05/29 00:14:20 rpantos
39 <rdar://problem/3508093> Runtime check to disable prod mdnsd on OS X.
41 Revision 1.8 2004/04/07 01:19:04 cheshire
42 Hash slot value should be unsigned
44 Revision 1.7 2004/02/14 06:34:57 cheshire
45 Use LogMsg instead of fprintf( stderr
47 Revision 1.6 2004/02/14 01:10:42 rpantos
48 Allow daemon to run if 'nobody' is not defined, with a warning. (For Roku HD1000.)
50 Revision 1.5 2004/02/05 07:45:43 cheshire
53 Revision 1.4 2004/01/28 21:14:23 cheshire
54 Reconcile debug_mode and gDebugLogging into a single flag (mDNS_DebugMode)
56 Revision 1.3 2004/01/19 19:51:46 cheshire
57 Fix compiler error (mixed declarations and code) on some versions of Linux
59 Revision 1.2 2003/12/11 03:03:51 rpantos
60 Clean up mDNSPosix so that it builds on OS X again.
62 Revision 1.1 2003/12/08 20:47:02 rpantos
63 Add support for mDNSResponder on Linux.
74 #include <sys/types.h>
76 #include "mDNSClientAPI.h"
77 #include "mDNSDebug.h"
78 #include "mDNSPosix.h"
79 #include "uds_daemon.h"
82 static void ParseCmdLinArgs( int argc
, char **argv
);
83 static void DumpStateLog( mDNS
*m
);
84 static mStatus
MainLoop( mDNS
*m
);
87 #define RR_CACHE_SIZE 500
88 static CacheRecord gRRCache
[RR_CACHE_SIZE
];
90 extern const char mDNSResponderVersionString
[];
92 int main( int argc
, char **argv
)
95 mDNS_PlatformSupport platformStorage
;
98 bzero( &mDNSRecord
, sizeof mDNSRecord
);
99 bzero( &platformStorage
, sizeof platformStorage
);
101 ParseCmdLinArgs( argc
, argv
);
103 err
= mDNS_Init( &mDNSRecord
, &platformStorage
, gRRCache
, RR_CACHE_SIZE
, mDNS_Init_AdvertiseLocalAddresses
,
104 mDNS_Init_NoInitCallback
, mDNS_Init_NoInitCallbackContext
);
106 if ( mStatus_NoError
== err
)
107 err
= udsserver_init( &mDNSRecord
);
109 // Now that we're finished with anything privileged, switch over to running as "nobody"
110 if ( mStatus_NoError
== err
)
112 const struct passwd
*pw
= getpwnam("nobody");
116 LogMsg("WARNING: mdnsd continuing as root because user \"nobody\" does not exist");
119 if ( mStatus_NoError
== err
)
120 err
= MainLoop( &mDNSRecord
);
122 mDNS_Close( &mDNSRecord
);
124 if (udsserver_exit() < 0)
125 LogMsg("ExitCallback: udsserver_exit failed");
127 #if MDNS_DEBUGMSGS > 0
128 printf( "mDNSResponder exiting normally with %ld\n", err
);
135 static void ParseCmdLinArgs( int argc
, char **argv
)
136 // Do appropriate things at startup with command line arguments. Calls exit() if unhappy.
140 if ( 0 == strcmp( argv
[1], "-debug"))
142 mDNS_DebugMode
= mDNStrue
;
145 printf( "Usage: mDNSResponder [-debug]\n");
148 if ( !mDNS_DebugMode
)
150 int result
= daemon( 0, 0);
154 LogMsg("Could not run as daemon - exiting");
160 LogMsg("The POSIX mDNSResponder should only be used on OS X for testing - exiting");
168 static void DumpStateLog( mDNS
*m
)
169 // Dump a little log of what we've been up to.
173 mDNSu32 CacheUsed
= 0, CacheActive
= 0;
174 mDNSs32 now
= mDNSPlatformTimeNow();
176 LogMsgIdent(mDNSResponderVersionString
, "---- BEGIN STATE LOG ----");
178 for (slot
= 0; slot
< CACHE_HASH_SLOTS
; slot
++)
180 mDNSu32 SlotUsed
= 0;
181 for (rr
= m
->rrcache_hash
[slot
]; rr
; rr
=rr
->next
)
183 mDNSs32 remain
= rr
->resrec
.rroriginalttl
- (now
- rr
->TimeRcvd
) / mDNSPlatformOneSecond
;
186 if (rr
->CRActiveQuestion
) CacheActive
++;
187 LogMsgNoIdent("%s%6ld %-6s%-6s%s", rr
->CRActiveQuestion
? "*" : " ", remain
, DNSTypeName(rr
->resrec
.rrtype
),
188 ((PosixNetworkInterface
*)rr
->resrec
.InterfaceID
)->intfName
, GetRRDisplayString(m
, rr
));
189 usleep(1000); // Limit rate a little so we don't flood syslog too fast
191 if (m
->rrcache_used
[slot
] != SlotUsed
)
192 LogMsgNoIdent("Cache use mismatch: rrcache_used[slot] is %lu, true count %lu", m
->rrcache_used
[slot
], SlotUsed
);
194 if (m
->rrcache_totalused
!= CacheUsed
)
195 LogMsgNoIdent("Cache use mismatch: rrcache_totalused is %lu, true count %lu", m
->rrcache_totalused
, CacheUsed
);
196 if (m
->rrcache_active
!= CacheActive
)
197 LogMsgNoIdent("Cache use mismatch: rrcache_active is %lu, true count %lu", m
->rrcache_active
, CacheActive
);
198 LogMsgNoIdent("Cache currently contains %lu records; %lu referenced by active questions", CacheUsed
, CacheActive
);
202 LogMsgIdent(mDNSResponderVersionString
, "---- END STATE LOG ----");
205 static mStatus
MainLoop( mDNS
*m
)
206 // Loop until we quit.
209 mDNSBool gotData
= mDNSfalse
;
211 mDNSPosixListenForSignalInEventLoop( SIGINT
);
212 mDNSPosixListenForSignalInEventLoop( SIGTERM
);
213 mDNSPosixListenForSignalInEventLoop( SIGUSR1
);
214 mDNSPosixListenForSignalInEventLoop( SIGPIPE
);
218 // Work out how long we expect to sleep before the next scheduled task
219 struct timeval timeout
;
222 // Only idle if we didn't find any data the last time around
225 mDNSs32 nextTimerEvent
= mDNS_Execute(m
);
227 nextTimerEvent
= udsserver_idle( nextTimerEvent
);
229 ticks
= nextTimerEvent
- mDNSPlatformTimeNow();
230 if (ticks
< 1) ticks
= 1;
232 else // otherwise call EventLoop again with 0 timemout
235 timeout
.tv_sec
= ticks
/ mDNSPlatformOneSecond
;
236 timeout
.tv_usec
= (ticks
% mDNSPlatformOneSecond
) * 1000000 / mDNSPlatformOneSecond
;
238 (void) mDNSPosixRunEventLoopOnce( m
, &timeout
, &signals
, &gotData
);
240 if ( sigismember( &signals
, SIGUSR1
))
242 if ( sigismember( &signals
, SIGPIPE
)) // happens when we try to write to a dead client; death should be detected soon in request_callback() and cleaned up.
243 LogMsg("Received SIGPIPE - ignoring");
244 if ( sigismember( &signals
, SIGINT
) || sigismember( &signals
, SIGTERM
))
252 // uds_daemon support ////////////////////////////////////////////////////////////
254 #if MDNS_MALLOC_DEBUGGING >= 2
255 #define LogMalloc LogMsg
257 #define LogMalloc(ARGS...) ((void)0)
261 mStatus
udsSupportAddFDToEventLoop( int fd
, udsEventCallback callback
, void *context
)
262 /* Support routine for uds_daemon.c */
264 // Depends on the fact that udsEventCallback == mDNSPosixEventCallback
265 return mDNSPosixAddFDToEventLoop( fd
, callback
, context
);
268 mStatus
udsSupportRemoveFDFromEventLoop( int fd
)
270 return mDNSPosixRemoveFDFromEventLoop( fd
);
273 #if MACOSX_MDNS_MALLOC_DEBUGGING >= 1
275 void *mallocL(char *msg
, unsigned int size
)
277 unsigned long *mem
= malloc(size
+8);
280 LogMsg("malloc( %s : %d ) failed", msg
, size
);
285 LogMalloc("malloc( %s : %lu ) = %p", msg
, size
, &mem
[2]);
288 //bzero(&mem[2], size);
289 memset(&mem
[2], 0xFF, size
);
290 // validatelists(&mDNSStorage);
295 void freeL(char *msg
, void *x
)
298 LogMsg("free( %s @ NULL )!", msg
);
301 unsigned long *mem
= ((unsigned long *)x
) - 2;
302 if (mem
[0] != 0xDEAD1234)
303 { LogMsg("free( %s @ %p ) !!!! NOT ALLOCATED !!!!", msg
, &mem
[2]); return; }
305 { LogMsg("free( %s : %ld @ %p) too big!", msg
, mem
[1], &mem
[2]); return; }
306 LogMalloc("free( %s : %ld @ %p)", msg
, mem
[1], &mem
[2]);
307 //bzero(mem, mem[1]+8);
308 memset(mem
, 0xDD, mem
[1]+8);
309 // validatelists(&mDNSStorage);
314 #endif // MACOSX_MDNS_MALLOC_DEBUGGING >= 1
318 // For convenience when using the "strings" command, this is the last thing in the file
319 #if mDNSResponderVersion > 1
320 mDNSexport
const char mDNSResponderVersionString
[] = "mDNSResponder-" STRINGIFY(mDNSResponderVersion
) " (" __DATE__
" " __TIME__
") ";
322 mDNSexport
const char mDNSResponderVersionString
[] = "mDNSResponder (Engineering Build) (" __DATE__
" " __TIME__
") ";