Home | History | Annotate | Line # | Download | only in mDNSPosix
PosixDaemon.c revision 1.11.2.1
      1       1.1    tsarna /* -*- Mode: C; tab-width: 4 -*-
      2       1.1    tsarna  *
      3       1.1    tsarna  * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved.
      4       1.1    tsarna  *
      5       1.1    tsarna  * Licensed under the Apache License, Version 2.0 (the "License");
      6       1.1    tsarna  * you may not use this file except in compliance with the License.
      7       1.1    tsarna  * You may obtain a copy of the License at
      8       1.9  christos  *
      9       1.1    tsarna  *     http://www.apache.org/licenses/LICENSE-2.0
     10       1.9  christos  *
     11       1.1    tsarna  * Unless required by applicable law or agreed to in writing, software
     12       1.1    tsarna  * distributed under the License is distributed on an "AS IS" BASIS,
     13       1.1    tsarna  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14       1.1    tsarna  * See the License for the specific language governing permissions and
     15       1.1    tsarna  * limitations under the License.
     16       1.1    tsarna 
     17       1.9  christos     File:		daemon.c
     18       1.1    tsarna 
     19       1.9  christos     Contains:	main & associated Application layer for mDNSResponder on Linux.
     20       1.1    tsarna 
     21       1.6    pettai  */
     22       1.1    tsarna 
     23       1.6    pettai #if __APPLE__
     24       1.6    pettai // In Mac OS X 10.5 and later trying to use the daemon function gives a daemon is deprecated
     25       1.6    pettai // error, which prevents compilation because we build with "-Werror".
     26       1.6    pettai // Since this is supposed to be portable cross-platform code, we don't care that daemon is
     27       1.6    pettai // deprecated on Mac OS X 10.5, so we use this preprocessor trick to eliminate the error message.
     28       1.6    pettai #define daemon yes_we_know_that_daemon_is_deprecated_in_os_x_10_5_thankyou
     29       1.6    pettai #endif
     30       1.1    tsarna 
     31       1.1    tsarna #include <stdio.h>
     32       1.1    tsarna #include <string.h>
     33       1.1    tsarna #include <unistd.h>
     34       1.1    tsarna #include <stdlib.h>
     35       1.1    tsarna #include <signal.h>
     36       1.1    tsarna #include <errno.h>
     37       1.1    tsarna #include <fcntl.h>
     38       1.1    tsarna #include <pwd.h>
     39       1.1    tsarna #include <sys/types.h>
     40       1.1    tsarna 
     41       1.6    pettai #if __APPLE__
     42       1.6    pettai #undef daemon
     43       1.6    pettai extern int daemon(int, int);
     44       1.6    pettai #endif
     45       1.6    pettai 
     46       1.1    tsarna #include "mDNSEmbeddedAPI.h"
     47       1.1    tsarna #include "mDNSPosix.h"
     48       1.9  christos #include "mDNSUNP.h"        // For daemon()
     49       1.1    tsarna #include "uds_daemon.h"
     50       1.1    tsarna #include "PlatformCommon.h"
     51  1.11.2.1  pgoyette #include "DNSCommon.h"
     52       1.1    tsarna 
     53       1.1    tsarna #define CONFIG_FILE "/etc/mdnsd.conf"
     54       1.1    tsarna static domainname DynDNSZone;                // Default wide-area zone for service registration
     55       1.1    tsarna static domainname DynDNSHostname;
     56       1.1    tsarna 
     57       1.1    tsarna #define RR_CACHE_SIZE 500
     58       1.1    tsarna static CacheEntity gRRCache[RR_CACHE_SIZE];
     59       1.1    tsarna static mDNS_PlatformSupport PlatformStorage;
     60       1.1    tsarna 
     61       1.1    tsarna mDNSlocal void mDNS_StatusCallback(mDNS *const m, mStatus result)
     62       1.9  christos {
     63       1.9  christos     (void)m; // Unused
     64       1.9  christos     if (result == mStatus_NoError)
     65       1.9  christos     {
     66       1.9  christos         // On successful registration of dot-local mDNS host name, daemon may want to check if
     67       1.9  christos         // any name conflict and automatic renaming took place, and if so, record the newly negotiated
     68       1.9  christos         // name in persistent storage for next time. It should also inform the user of the name change.
     69       1.9  christos         // On Mac OS X we store the current dot-local mDNS host name in the SCPreferences store,
     70       1.9  christos         // and notify the user with a CFUserNotification.
     71       1.9  christos     }
     72       1.9  christos     else if (result == mStatus_ConfigChanged)
     73       1.9  christos     {
     74       1.9  christos         udsserver_handle_configchange(m);
     75       1.9  christos     }
     76       1.9  christos     else if (result == mStatus_GrowCache)
     77       1.9  christos     {
     78       1.9  christos         // Allocate another chunk of cache storage
     79       1.9  christos         CacheEntity *storage = malloc(sizeof(CacheEntity) * RR_CACHE_SIZE);
     80       1.9  christos         if (storage) mDNS_GrowCache(m, storage, RR_CACHE_SIZE);
     81       1.9  christos     }
     82       1.9  christos }
     83       1.1    tsarna 
     84       1.1    tsarna // %%% Reconfigure() probably belongs in the platform support layer (mDNSPosix.c), not the daemon cde
     85       1.1    tsarna // -- all client layers running on top of mDNSPosix.c need to handle network configuration changes,
     86       1.1    tsarna // not only the Unix Domain Socket Daemon
     87       1.1    tsarna 
     88       1.1    tsarna static void Reconfigure(mDNS *m)
     89       1.9  christos {
     90       1.9  christos     mDNSAddr DynDNSIP;
     91       1.9  christos     const mDNSAddr dummy = { mDNSAddrType_IPv4, { { { 1, 1, 1, 1 } } } };;
     92       1.9  christos     mDNS_SetPrimaryInterfaceInfo(m, NULL, NULL, NULL);
     93  1.11.2.1  pgoyette     mDNS_Lock(m);
     94       1.9  christos     if (ParseDNSServers(m, uDNS_SERVERS_FILE) < 0)
     95       1.9  christos         LogMsg("Unable to parse DNS server list. Unicast DNS-SD unavailable");
     96  1.11.2.1  pgoyette     mDNS_Unlock(m);
     97       1.9  christos     ReadDDNSSettingsFromConfFile(m, CONFIG_FILE, &DynDNSHostname, &DynDNSZone, NULL);
     98       1.9  christos     mDNSPlatformSourceAddrForDest(&DynDNSIP, &dummy);
     99       1.9  christos     if (DynDNSHostname.c[0]) mDNS_AddDynDNSHostName(m, &DynDNSHostname, NULL, NULL);
    100       1.9  christos     if (DynDNSIP.type) mDNS_SetPrimaryInterfaceInfo(m, &DynDNSIP, NULL, NULL);
    101       1.9  christos     mDNS_ConfigChanged(m);
    102       1.9  christos }
    103       1.1    tsarna 
    104       1.1    tsarna // Do appropriate things at startup with command line arguments. Calls exit() if unhappy.
    105       1.1    tsarna mDNSlocal void ParseCmdLinArgs(int argc, char **argv)
    106       1.9  christos {
    107       1.9  christos     if (argc > 1)
    108       1.9  christos     {
    109       1.9  christos         if (0 == strcmp(argv[1], "-debug")) mDNS_DebugMode = mDNStrue;
    110       1.9  christos         else printf("Usage: %s [-debug]\n", argv[0]);
    111       1.9  christos     }
    112       1.9  christos 
    113       1.9  christos     if (!mDNS_DebugMode)
    114       1.9  christos     {
    115       1.9  christos         int result = daemon(0, 0);
    116       1.9  christos         if (result != 0) { LogMsg("Could not run as daemon - exiting"); exit(result); }
    117       1.1    tsarna #if __APPLE__
    118       1.9  christos         LogMsg("The POSIX mdnsd should only be used on OS X for testing - exiting");
    119       1.9  christos         exit(-1);
    120       1.1    tsarna #endif
    121       1.9  christos     }
    122       1.9  christos }
    123       1.1    tsarna 
    124      1.10  christos mDNSlocal void DumpStateLog()
    125       1.1    tsarna // Dump a little log of what we've been up to.
    126       1.9  christos {
    127      1.10  christos 	LogMsg("---- BEGIN STATE LOG ----");
    128      1.10  christos     udsserver_info();
    129       1.9  christos     LogMsg("----  END STATE LOG  ----");
    130       1.9  christos }
    131       1.9  christos 
    132       1.9  christos mDNSlocal mStatus MainLoop(mDNS *m) // Loop until we quit.
    133       1.9  christos {
    134       1.9  christos     sigset_t signals;
    135       1.9  christos     mDNSBool gotData = mDNSfalse;
    136       1.9  christos 
    137       1.9  christos     mDNSPosixListenForSignalInEventLoop(SIGINT);
    138       1.9  christos     mDNSPosixListenForSignalInEventLoop(SIGTERM);
    139       1.9  christos     mDNSPosixListenForSignalInEventLoop(SIGUSR1);
    140       1.9  christos     mDNSPosixListenForSignalInEventLoop(SIGPIPE);
    141       1.9  christos     mDNSPosixListenForSignalInEventLoop(SIGHUP) ;
    142       1.9  christos 
    143       1.9  christos     for (; ;)
    144       1.9  christos     {
    145       1.9  christos         // Work out how long we expect to sleep before the next scheduled task
    146       1.9  christos         struct timeval timeout;
    147       1.9  christos         mDNSs32 ticks;
    148       1.9  christos 
    149       1.9  christos         // Only idle if we didn't find any data the last time around
    150       1.9  christos         if (!gotData)
    151       1.9  christos         {
    152       1.9  christos             mDNSs32 nextTimerEvent = mDNS_Execute(m);
    153       1.9  christos             nextTimerEvent = udsserver_idle(nextTimerEvent);
    154       1.9  christos             ticks = nextTimerEvent - mDNS_TimeNow(m);
    155       1.9  christos             if (ticks < 1) ticks = 1;
    156       1.4    tsarna         }
    157       1.9  christos         else    // otherwise call EventLoop again with 0 timemout
    158       1.9  christos             ticks = 0;
    159       1.2    tsarna 
    160       1.9  christos         timeout.tv_sec = ticks / mDNSPlatformOneSecond;
    161       1.9  christos         timeout.tv_usec = (ticks % mDNSPlatformOneSecond) * 1000000 / mDNSPlatformOneSecond;
    162       1.1    tsarna 
    163       1.9  christos         (void) mDNSPosixRunEventLoopOnce(m, &timeout, &signals, &gotData);
    164       1.1    tsarna 
    165       1.9  christos         if (sigismember(&signals, SIGHUP )) Reconfigure(m);
    166      1.10  christos         if (sigismember(&signals, SIGUSR1)) DumpStateLog();
    167       1.9  christos         // SIGPIPE happens when we try to write to a dead client; death should be detected soon in request_callback() and cleaned up.
    168       1.9  christos         if (sigismember(&signals, SIGPIPE)) LogMsg("Received SIGPIPE - ignoring");
    169       1.9  christos         if (sigismember(&signals, SIGINT) || sigismember(&signals, SIGTERM)) break;
    170       1.9  christos     }
    171       1.9  christos     return EINTR;
    172       1.9  christos }
    173       1.1    tsarna 
    174       1.1    tsarna int main(int argc, char **argv)
    175       1.9  christos {
    176       1.9  christos     mStatus err;
    177       1.9  christos 
    178       1.9  christos     ParseCmdLinArgs(argc, argv);
    179       1.9  christos 
    180       1.9  christos     LogMsg("%s starting", mDNSResponderVersionString);
    181       1.1    tsarna 
    182       1.9  christos     err = mDNS_Init(&mDNSStorage, &PlatformStorage, gRRCache, RR_CACHE_SIZE, mDNS_Init_AdvertiseLocalAddresses,
    183       1.9  christos                     mDNS_StatusCallback, mDNS_Init_NoInitCallbackContext);
    184       1.1    tsarna 
    185       1.9  christos     if (mStatus_NoError == err)
    186       1.9  christos         err = udsserver_init(mDNSNULL, 0);
    187       1.1    tsarna 
    188       1.9  christos     Reconfigure(&mDNSStorage);
    189       1.9  christos 
    190       1.9  christos     // Now that we're finished with anything privileged, switch over to running as "nobody"
    191       1.9  christos     if (mStatus_NoError == err)
    192       1.9  christos     {
    193       1.9  christos         const struct passwd *pw = getpwnam("nobody");
    194       1.9  christos         if (pw != NULL)
    195       1.9  christos             setuid(pw->pw_uid);
    196       1.9  christos         else
    197       1.9  christos             LogMsg("WARNING: mdnsd continuing as root because user \"nobody\" does not exist");
    198       1.9  christos     }
    199       1.9  christos 
    200       1.9  christos     if (mStatus_NoError == err)
    201       1.9  christos         err = MainLoop(&mDNSStorage);
    202       1.9  christos 
    203       1.9  christos     LogMsg("%s stopping", mDNSResponderVersionString);
    204       1.9  christos 
    205       1.9  christos     mDNS_Close(&mDNSStorage);
    206       1.9  christos 
    207       1.9  christos     if (udsserver_exit() < 0)
    208       1.9  christos         LogMsg("ExitCallback: udsserver_exit failed");
    209       1.1    tsarna 
    210       1.1    tsarna  #if MDNS_DEBUGMSGS > 0
    211       1.9  christos     printf("mDNSResponder exiting normally with %ld\n", err);
    212       1.1    tsarna  #endif
    213       1.9  christos 
    214       1.9  christos     return err;
    215       1.9  christos }
    216       1.1    tsarna 
    217       1.1    tsarna //		uds_daemon support		////////////////////////////////////////////////////////////
    218       1.1    tsarna 
    219       1.6    pettai mStatus udsSupportAddFDToEventLoop(int fd, udsEventCallback callback, void *context, void **platform_data)
    220       1.1    tsarna /* Support routine for uds_daemon.c */
    221       1.9  christos {
    222       1.9  christos     // Depends on the fact that udsEventCallback == mDNSPosixEventCallback
    223       1.9  christos     (void) platform_data;
    224       1.9  christos     return mDNSPosixAddFDToEventLoop(fd, callback, context);
    225       1.9  christos }
    226       1.1    tsarna 
    227       1.6    pettai int udsSupportReadFD(dnssd_sock_t fd, char *buf, int len, int flags, void *platform_data)
    228       1.9  christos {
    229       1.9  christos     (void) platform_data;
    230       1.9  christos     return recv(fd, buf, len, flags);
    231       1.9  christos }
    232       1.9  christos 
    233       1.9  christos mStatus udsSupportRemoveFDFromEventLoop(int fd, void *platform_data)        // Note: This also CLOSES the file descriptor
    234       1.9  christos {
    235       1.9  christos     mStatus err = mDNSPosixRemoveFDFromEventLoop(fd);
    236       1.9  christos     (void) platform_data;
    237       1.9  christos     close(fd);
    238       1.9  christos     return err;
    239       1.9  christos }
    240       1.1    tsarna 
    241      1.10  christos mDNSexport void RecordUpdatedNiceLabel(mDNSs32 delay)
    242       1.9  christos {
    243       1.9  christos     (void)delay;
    244       1.9  christos     // No-op, for now
    245       1.9  christos }
    246       1.1    tsarna 
    247       1.1    tsarna #if _BUILDING_XCODE_PROJECT_
    248       1.1    tsarna // If the process crashes, then this string will be magically included in the automatically-generated crash log
    249       1.1    tsarna const char *__crashreporter_info__ = mDNSResponderVersionString_SCCS + 5;
    250       1.9  christos asm (".desc ___crashreporter_info__, 0x10");
    251       1.1    tsarna #endif
    252       1.1    tsarna 
    253       1.1    tsarna // For convenience when using the "strings" command, this is the last thing in the file
    254       1.1    tsarna #if mDNSResponderVersion > 1
    255      1.11  christos mDNSexport const char mDNSResponderVersionString_SCCS[] = "@(#) mDNSResponder-" STRINGIFY(mDNSResponderVersion)
    256      1.11  christos #ifndef MDNS_VERSIONSTR_NODTS
    257      1.11  christos     " (" __DATE__ " " __TIME__ ")"
    258      1.11  christos #endif
    259      1.11  christos ;
    260       1.1    tsarna #else
    261      1.11  christos mDNSexport const char mDNSResponderVersionString_SCCS[] = "@(#) mDNSResponder (Engineering Build)"
    262      1.11  christos #ifndef MDNS_VERSIONSTR_NODTS
    263      1.11  christos     " (" __DATE__ " " __TIME__ ")"
    264      1.11  christos #endif
    265      1.11  christos ;
    266       1.1    tsarna #endif
    267