You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
643 lines
19 KiB
643 lines
19 KiB
/***************************************************************************/
|
|
/* */
|
|
/* Project: OpenSLP - OpenSource implementation of Service Location */
|
|
/* Protocol Version 2 */
|
|
/* */
|
|
/* File: slpd_main.c */
|
|
/* */
|
|
/* Abstract: Main daemon loop */
|
|
/* */
|
|
/*-------------------------------------------------------------------------*/
|
|
/* */
|
|
/* Please submit patches to http://www.openslp.org */
|
|
/* */
|
|
/*-------------------------------------------------------------------------*/
|
|
/* */
|
|
/* Copyright (C) 2000 Caldera Systems, Inc */
|
|
/* All rights reserved. */
|
|
/* */
|
|
/* Redistribution and use in source and binary forms, with or without */
|
|
/* modification, are permitted provided that the following conditions are */
|
|
/* met: */
|
|
/* */
|
|
/* Redistributions of source code must retain the above copyright */
|
|
/* notice, this list of conditions and the following disclaimer. */
|
|
/* */
|
|
/* Redistributions in binary form must reproduce the above copyright */
|
|
/* notice, this list of conditions and the following disclaimer in */
|
|
/* the documentation and/or other materials provided with the */
|
|
/* distribution. */
|
|
/* */
|
|
/* Neither the name of Caldera Systems nor the names of its */
|
|
/* contributors may be used to endorse or promote products derived */
|
|
/* from this software without specific prior written permission. */
|
|
/* */
|
|
/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
|
|
/* `AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
|
|
/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */
|
|
/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE CALDERA */
|
|
/* SYSTEMS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
|
|
/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
|
|
/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */
|
|
/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */
|
|
/* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
|
|
/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */
|
|
/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
|
|
/* */
|
|
/***************************************************************************/
|
|
|
|
#include "slpd.h"
|
|
|
|
/*=========================================================================*/
|
|
/* slpd includes */
|
|
/*=========================================================================*/
|
|
#include "slpd_log.h"
|
|
#include "slpd_socket.h"
|
|
#include "slpd_incoming.h"
|
|
#include "slpd_outgoing.h"
|
|
#include "slpd_database.h"
|
|
#include "slpd_cmdline.h"
|
|
#include "slpd_knownda.h"
|
|
#include "slpd_property.h"
|
|
#ifdef ENABLE_SLPv2_SECURITY
|
|
#include "slpd_spi.h"
|
|
#endif
|
|
|
|
/*=========================================================================*/
|
|
/* common code includes */
|
|
/*=========================================================================*/
|
|
#include "slp_xmalloc.h"
|
|
#include "slp_xid.h"
|
|
|
|
|
|
/*==========================================================================*/
|
|
int G_SIGALRM;
|
|
int G_SIGTERM;
|
|
int G_SIGHUP;
|
|
#ifdef DEBUG
|
|
int G_SIGINT; /* Signal being used for dumping registrations */
|
|
#endif
|
|
/*==========================================================================*/
|
|
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
void LoadFdSets(SLPList* socklist,
|
|
int* highfd,
|
|
fd_set* readfds,
|
|
fd_set* writefds)
|
|
/*-------------------------------------------------------------------------*/
|
|
{
|
|
SLPDSocket* sock = 0;
|
|
SLPDSocket* del = 0;
|
|
|
|
sock = (SLPDSocket*)socklist->head;
|
|
while(sock)
|
|
{
|
|
if(sock->fd > *highfd)
|
|
{
|
|
*highfd = sock->fd;
|
|
}
|
|
|
|
switch(sock->state)
|
|
{
|
|
case DATAGRAM_UNICAST:
|
|
case DATAGRAM_MULTICAST:
|
|
case DATAGRAM_BROADCAST:
|
|
FD_SET(sock->fd,readfds);
|
|
break;
|
|
|
|
case SOCKET_LISTEN:
|
|
if(socklist->count < SLPD_MAX_SOCKETS)
|
|
{
|
|
FD_SET(sock->fd,readfds);
|
|
}
|
|
break;
|
|
|
|
case STREAM_READ:
|
|
case STREAM_READ_FIRST:
|
|
FD_SET(sock->fd,readfds);
|
|
break;
|
|
|
|
case STREAM_WRITE:
|
|
case STREAM_WRITE_FIRST:
|
|
case STREAM_CONNECT_BLOCK:
|
|
FD_SET(sock->fd,writefds);
|
|
break;
|
|
|
|
case SOCKET_CLOSE:
|
|
del = sock;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
sock = (SLPDSocket*)sock->listitem.next;
|
|
|
|
if(del)
|
|
{
|
|
SLPDSocketFree((SLPDSocket*)SLPListUnlink(socklist,(SLPListItem*)del));
|
|
del = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
void HandleSigTerm()
|
|
/*------------------------------------------------------------------------*/
|
|
{
|
|
struct timeval timeout;
|
|
fd_set readfds;
|
|
fd_set writefds;
|
|
int highfd = 0;
|
|
int fdcount = 0;
|
|
|
|
SLPDLog("****************************************\n");
|
|
SLPDLogTime();
|
|
SLPDLog("SLPD daemon shutting down\n");
|
|
SLPDLog("****************************************\n");
|
|
|
|
/* close all incoming sockets */
|
|
SLPDIncomingDeinit();
|
|
|
|
/* unregister with all DAs */
|
|
SLPDKnownDADeinit();
|
|
|
|
timeout.tv_sec = 5;
|
|
timeout.tv_usec = 0;
|
|
|
|
/* Do a dead DA passive advert to tell everyone we're goin' down */
|
|
SLPDKnownDAPassiveDAAdvert(0, 1);
|
|
|
|
/* if possible wait until all outgoing socket are done and closed */
|
|
while(SLPDOutgoingDeinit(1))
|
|
{
|
|
FD_ZERO(&writefds);
|
|
FD_ZERO(&readfds);
|
|
LoadFdSets(&G_OutgoingSocketList, &highfd, &readfds,&writefds);
|
|
fdcount = select(highfd+1,&readfds,&writefds,0,&timeout);
|
|
if(fdcount == 0)
|
|
{
|
|
break;
|
|
}
|
|
|
|
SLPDOutgoingHandler(&fdcount,&readfds,&writefds);
|
|
}
|
|
|
|
SLPDOutgoingDeinit(0);
|
|
|
|
SLPDLog("****************************************\n");
|
|
SLPDLogTime();
|
|
SLPDLog("SLPD daemon shut down\n");
|
|
SLPDLog("****************************************\n");
|
|
|
|
#ifdef DEBUG
|
|
#ifdef ENABLE_SLPv2_SECURITY
|
|
SLPDSpiDeinit();
|
|
#endif
|
|
SLPDDatabaseDeinit();
|
|
SLPDPropertyDeinit();
|
|
SLPDLogFileClose();
|
|
xmalloc_deinit();
|
|
#endif
|
|
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
void HandleSigHup()
|
|
/*------------------------------------------------------------------------*/
|
|
{
|
|
/* Reinitialize */
|
|
SLPDLog("****************************************\n");
|
|
SLPDLogTime();
|
|
SLPDLog("SLPD daemon reset by SIGHUP\n");
|
|
SLPDLog("****************************************\n\n");
|
|
|
|
/* unregister with all DAs */
|
|
SLPDKnownDADeinit();
|
|
|
|
/* re-read properties */
|
|
SLPDPropertyInit(G_SlpdCommandLine.cfgfile);
|
|
|
|
#ifdef ENABLE_SLPv2_SECURITY
|
|
/* Re-initialize SPI stuff*/
|
|
SLPDSpiInit(G_SlpdCommandLine.spifile);
|
|
#endif
|
|
|
|
/* Re-read the static registration file (slp.reg)*/
|
|
SLPDDatabaseReInit(G_SlpdCommandLine.regfile);
|
|
|
|
/* Rebuild Known DA database */
|
|
SLPDKnownDAInit();
|
|
|
|
SLPDLog("****************************************\n");
|
|
SLPDLogTime();
|
|
SLPDLog("SLPD daemon reset finished\n");
|
|
SLPDLog("****************************************\n\n");
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
void HandleSigAlrm()
|
|
/*------------------------------------------------------------------------*/
|
|
{
|
|
SLPDIncomingAge(SLPD_AGE_INTERVAL);
|
|
SLPDOutgoingAge(SLPD_AGE_INTERVAL);
|
|
SLPDKnownDAImmortalRefresh(SLPD_AGE_INTERVAL);
|
|
SLPDKnownDAPassiveDAAdvert(SLPD_AGE_INTERVAL,0);
|
|
SLPDKnownDAActiveDiscovery(SLPD_AGE_INTERVAL);
|
|
SLPDDatabaseAge(SLPD_AGE_INTERVAL,G_SlpdProperty.isDA);
|
|
}
|
|
|
|
|
|
#ifdef DEBUG
|
|
/*--------------------------------------------------------------------------*/
|
|
void HandleSigInt()
|
|
/*--------------------------------------------------------------------------*/
|
|
{
|
|
SLPDIncomingSocketDump();
|
|
SLPDOutgoingSocketDump();
|
|
SLPDKnownDADump();
|
|
SLPDDatabaseDump();
|
|
}
|
|
#endif
|
|
|
|
|
|
#ifndef _WIN32
|
|
/*-------------------------------------------------------------------------*/
|
|
int CheckPid(const char* pidfile)
|
|
/* Check a pid file to see if slpd is already running */
|
|
/* */
|
|
/* Returns: 0 on success. non-zero on failure */
|
|
/*-------------------------------------------------------------------------*/
|
|
{
|
|
pid_t pid;
|
|
FILE* fd;
|
|
char pidstr[14];
|
|
|
|
/*------------------------------------------*/
|
|
/* make sure that we're not running already */
|
|
/*------------------------------------------*/
|
|
/* read the pid from the file */
|
|
fd = fopen(pidfile,"r");
|
|
if(fd)
|
|
{
|
|
memset(pidstr,0,14);
|
|
fread(pidstr,13,1,fd);
|
|
pid = atoi(pidstr);
|
|
if(pid)
|
|
{
|
|
if(kill(pid,0) == 0)
|
|
{
|
|
/* we are already running */
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
fclose(fd);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
int WritePid(const char* pidfile, pid_t pid)
|
|
/* Write the pid file */
|
|
/* */
|
|
/* Returns: 0 on success. non-zero on failure */
|
|
/*-------------------------------------------------------------------------*/
|
|
{
|
|
FILE* fd;
|
|
char pidstr[14];
|
|
|
|
/* write my pid to the pidfile */
|
|
fd = fopen(pidfile,"w");
|
|
if(fd)
|
|
{
|
|
sprintf(pidstr,"%i",(int)pid);
|
|
fwrite(pidstr,strlen(pidstr),1,fd);
|
|
fclose(fd);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
int Daemonize(const char* pidfile)
|
|
/* Turn the calling process into a daemon (detach from tty setuid(), etc */
|
|
/* */
|
|
/* Returns: zero on success non-zero if slpd could not daemonize (or if */
|
|
/* slpd is already running . */
|
|
/*-------------------------------------------------------------------------*/
|
|
{
|
|
FILE* fd;
|
|
struct passwd* pwent;
|
|
pid_t pid;
|
|
char pidstr[14];
|
|
|
|
/* fork() if we should detach */
|
|
if(G_SlpdCommandLine.detach)
|
|
{
|
|
pid = fork();
|
|
}
|
|
else
|
|
{
|
|
pid = getpid();
|
|
}
|
|
|
|
/* parent or child? */
|
|
switch(pid)
|
|
{
|
|
case -1:
|
|
return -1;
|
|
case 0:
|
|
/* child lives */
|
|
break;
|
|
|
|
default:
|
|
/* parent writes pid (or child) pid file and dies */
|
|
fd = fopen(pidfile,"w");
|
|
if(fd)
|
|
{
|
|
sprintf(pidstr,"%i",(int)pid);
|
|
fwrite(pidstr,strlen(pidstr),1,fd);
|
|
fclose(fd);
|
|
}
|
|
if(G_SlpdCommandLine.detach)
|
|
{
|
|
exit(0);
|
|
}
|
|
break;
|
|
}
|
|
|
|
close(0);
|
|
close(1);
|
|
close(2);
|
|
setsid(); /* will only fail if we are already the process group leader */
|
|
|
|
/*----------------*/
|
|
/* suid to daemon */
|
|
/*----------------*/
|
|
/* TODO: why do the following lines mess up my signal handlers? */
|
|
pwent = getpwnam("daemon");
|
|
if(pwent)
|
|
{
|
|
if(setgroups(1, &pwent->pw_gid) < 0 ||
|
|
setgid(pwent->pw_gid) < 0 ||
|
|
setuid(pwent->pw_uid) < 0)
|
|
{
|
|
/* TODO: should we log here and return fail */
|
|
exit(1);
|
|
}
|
|
}
|
|
else
|
|
exit(1);
|
|
|
|
/*--------------------*/
|
|
/* Set cwd to / (root)*/
|
|
/*--------------------*/
|
|
chdir("/");
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
void SignalHandler(int signum)
|
|
/*--------------------------------------------------------------------------*/
|
|
{
|
|
switch(signum)
|
|
{
|
|
case SIGALRM:
|
|
G_SIGALRM = 1;
|
|
break;
|
|
|
|
case SIGTERM:
|
|
G_SIGTERM = 1;
|
|
break;
|
|
|
|
case SIGHUP:
|
|
G_SIGHUP = 1;
|
|
break;
|
|
|
|
#ifdef DEBUG
|
|
case SIGINT:
|
|
G_SIGINT = 1;
|
|
break;
|
|
#endif
|
|
|
|
case SIGPIPE:
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
int SetUpSignalHandlers()
|
|
/*-------------------------------------------------------------------------*/
|
|
{
|
|
int result;
|
|
struct sigaction sa;
|
|
|
|
sa.sa_handler = SignalHandler;
|
|
sigemptyset(&sa.sa_mask);
|
|
sa.sa_flags = 0;//SA_ONESHOT;
|
|
#if defined(HAVE_SA_RESTORER)
|
|
sa.sa_restorer = 0;
|
|
#endif
|
|
|
|
result = sigaction(SIGALRM,&sa,0);
|
|
result |= sigaction(SIGTERM,&sa,0);
|
|
result |= sigaction(SIGPIPE,&sa,0);
|
|
|
|
#ifdef DEBUG
|
|
result |= sigaction(SIGINT,&sa,0);
|
|
#endif
|
|
|
|
signal(SIGHUP,SignalHandler);
|
|
//result |= sigaction(SIGHUP,&sa,0);
|
|
|
|
return result;
|
|
}
|
|
|
|
/*=========================================================================*/
|
|
int main(int argc, char* argv[])
|
|
/*=========================================================================*/
|
|
{
|
|
fd_set readfds;
|
|
fd_set writefds;
|
|
int highfd;
|
|
int fdcount = 0;
|
|
|
|
#ifdef DEBUG
|
|
xmalloc_init("/var/log/slpd_xmalloc.log",0);
|
|
#endif
|
|
|
|
/*------------------------*/
|
|
/* Parse the command line */
|
|
/*------------------------*/
|
|
if(SLPDParseCommandLine(argc,argv))
|
|
{
|
|
SLPDFatal("Invalid command line\n");
|
|
}
|
|
|
|
/*------------------------------*/
|
|
/* Make sure we are root */
|
|
/*------------------------------*/
|
|
if(getuid() != 0)
|
|
{
|
|
SLPDFatal("slpd must be started by root\n");
|
|
}
|
|
|
|
/*--------------------------------------*/
|
|
/* Make sure we are not already running */
|
|
/*--------------------------------------*/
|
|
if(CheckPid(G_SlpdCommandLine.pidfile))
|
|
{
|
|
SLPDFatal("slpd is already running. Check %s\n",
|
|
G_SlpdCommandLine.pidfile);
|
|
}
|
|
|
|
/*------------------------------*/
|
|
/* Initialize the log file */
|
|
/*------------------------------*/
|
|
if(SLPDLogFileOpen(G_SlpdCommandLine.logfile, 1))
|
|
{
|
|
SLPDFatal("Could not open logfile %s\n",G_SlpdCommandLine.logfile);
|
|
}
|
|
|
|
/*------------------------*/
|
|
/* Seed the XID generator */
|
|
/*------------------------*/
|
|
SLPXidSeed();
|
|
|
|
/*---------------------*/
|
|
/* Log startup message */
|
|
/*---------------------*/
|
|
SLPDLog("****************************************\n");
|
|
SLPDLogTime();
|
|
SLPDLog("SLPD daemon started\n");
|
|
SLPDLog("****************************************\n");
|
|
SLPDLog("Command line = %s\n",argv[0]);
|
|
SLPDLog("Using configuration file = %s\n",G_SlpdCommandLine.cfgfile);
|
|
SLPDLog("Using registration file = %s\n",G_SlpdCommandLine.regfile);
|
|
#ifdef ENABLE_SLPv2_SECURITY
|
|
SLPDLog("Using SPI file = %s\n",G_SlpdCommandLine.spifile);
|
|
#endif
|
|
|
|
/*--------------------------------------------------*/
|
|
/* Initialize for the first time */
|
|
/*--------------------------------------------------*/
|
|
if(SLPDPropertyInit(G_SlpdCommandLine.cfgfile) ||
|
|
#ifdef ENABLE_SLPv2_SECURITY
|
|
SLPDSpiInit(G_SlpdCommandLine.spifile) ||
|
|
#endif
|
|
SLPDDatabaseInit(G_SlpdCommandLine.regfile) ||
|
|
SLPDIncomingInit() ||
|
|
SLPDOutgoingInit() ||
|
|
SLPDKnownDAInit())
|
|
{
|
|
SLPDFatal("slpd initialization failed\n");
|
|
}
|
|
SLPDLog("Agent Interfaces = %s\n",G_SlpdProperty.interfaces);
|
|
SLPDLog("Agent URL = %s\n",G_SlpdProperty.myUrl);
|
|
|
|
/*---------------------------*/
|
|
/* make slpd run as a daemon */
|
|
/*---------------------------*/
|
|
if(Daemonize(G_SlpdCommandLine.pidfile))
|
|
{
|
|
SLPDFatal("Could not daemonize\n");
|
|
}
|
|
|
|
/*-----------------------*/
|
|
/* Setup signal handlers */
|
|
/*-----------------------*/
|
|
if(SetUpSignalHandlers())
|
|
{
|
|
SLPDFatal("Error setting up signal handlers.\n");
|
|
}
|
|
|
|
/*------------------------------*/
|
|
/* Set up alarm to age database */
|
|
/*------------------------------*/
|
|
alarm(SLPD_AGE_INTERVAL);
|
|
|
|
/*-----------*/
|
|
/* Main loop */
|
|
/*-----------*/
|
|
SLPDLog("Startup complete entering main run loop ...\n\n");
|
|
G_SIGALRM = 0;
|
|
G_SIGTERM = 0;
|
|
G_SIGHUP = 0;
|
|
#ifdef DEBUG
|
|
G_SIGINT = 0;
|
|
#endif
|
|
|
|
while(G_SIGTERM == 0)
|
|
{
|
|
/*--------------------------------------------------------*/
|
|
/* Load the fdsets up with all valid sockets in the list */
|
|
/*--------------------------------------------------------*/
|
|
highfd = 0;
|
|
FD_ZERO(&readfds);
|
|
FD_ZERO(&writefds);
|
|
LoadFdSets(&G_IncomingSocketList, &highfd, &readfds,&writefds);
|
|
LoadFdSets(&G_OutgoingSocketList, &highfd, &readfds,&writefds);
|
|
|
|
/*--------------------------------------------------*/
|
|
/* Before select(), check to see if we got a signal */
|
|
/*--------------------------------------------------*/
|
|
if(G_SIGALRM || G_SIGHUP)
|
|
{
|
|
goto HANDLE_SIGNAL;
|
|
}
|
|
|
|
/*-------------*/
|
|
/* Main select */
|
|
/*-------------*/
|
|
fdcount = select(highfd+1,&readfds,&writefds,0,0);
|
|
if(fdcount > 0) /* fdcount will be < 0 when interrupted by a signal */
|
|
{
|
|
SLPDIncomingHandler(&fdcount,&readfds,&writefds);
|
|
SLPDOutgoingHandler(&fdcount,&readfds,&writefds);
|
|
}
|
|
|
|
/*----------------*/
|
|
/* Handle signals */
|
|
/*----------------*/
|
|
HANDLE_SIGNAL:
|
|
if(G_SIGHUP)
|
|
{
|
|
HandleSigHup();
|
|
G_SIGHUP = 0;
|
|
}
|
|
if(G_SIGALRM)
|
|
{
|
|
HandleSigAlrm();
|
|
G_SIGALRM = 0;
|
|
alarm(SLPD_AGE_INTERVAL);
|
|
}
|
|
#ifdef DEBUG
|
|
if (G_SIGINT)
|
|
{
|
|
HandleSigInt();
|
|
G_SIGINT = 0;
|
|
}
|
|
#endif
|
|
|
|
} /* End of main loop */
|
|
|
|
/* Got SIGTERM */
|
|
HandleSigTerm();
|
|
|
|
return 0;
|
|
}
|
|
#endif /*ifndef _WIN32 */
|
|
|
|
|
|
|