pluto: Check for processes with the PID stored in pluto.pid.
This commit is contained in:
+74
-43
@@ -29,6 +29,7 @@
|
|||||||
#include <arpa/nameser.h> /* missing from <resolv.h> on old systems */
|
#include <arpa/nameser.h> /* missing from <resolv.h> on old systems */
|
||||||
#include <sys/queue.h>
|
#include <sys/queue.h>
|
||||||
#include <sys/prctl.h>
|
#include <sys/prctl.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <grp.h>
|
#include <grp.h>
|
||||||
|
|
||||||
@@ -84,6 +85,23 @@
|
|||||||
*/
|
*/
|
||||||
#define DEFAULT_THREADS 4
|
#define DEFAULT_THREADS 4
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PID file, in which pluto stores its process id
|
||||||
|
*/
|
||||||
|
static char pluto_lock[sizeof(ctl_addr.sun_path)] = DEFAULT_CTLBASE LOCK_SUFFIX;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TRUE if the lock has been checked. This helps to avoid any unintended
|
||||||
|
* deletion of the lock or control socket.
|
||||||
|
*/
|
||||||
|
static bool pluto_lock_checked = FALSE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Global reference to PID file (required to truncate, if undeletable)
|
||||||
|
*/
|
||||||
|
static FILE *pidfile = NULL;
|
||||||
|
|
||||||
|
|
||||||
static void usage(const char *mess)
|
static void usage(const char *mess)
|
||||||
{
|
{
|
||||||
if (mess != NULL && *mess != '\0')
|
if (mess != NULL && *mess != '\0')
|
||||||
@@ -148,59 +166,66 @@ static void usage(const char *mess)
|
|||||||
exit_pluto(mess == NULL? 0 : 1);
|
exit_pluto(mess == NULL? 0 : 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool check_lock()
|
||||||
/* lock file support
|
|
||||||
* - provides convenient way for scripts to find Pluto's pid
|
|
||||||
* - prevents multiple Plutos competing for the same port
|
|
||||||
* - same basename as unix domain control socket
|
|
||||||
* NOTE: will not take account of sharing LOCK_DIR with other systems.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static char pluto_lock[sizeof(ctl_addr.sun_path)] = DEFAULT_CTLBASE LOCK_SUFFIX;
|
|
||||||
static bool pluto_lock_created = FALSE;
|
|
||||||
|
|
||||||
/* create lockfile, or die in the attempt */
|
|
||||||
static int create_lock(void)
|
|
||||||
{
|
{
|
||||||
int fd = open(pluto_lock, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC
|
struct stat stb;
|
||||||
, S_IRUSR | S_IRGRP | S_IROTH);
|
FILE *fpid;
|
||||||
|
|
||||||
if (fd < 0)
|
if (stat(pluto_lock, &stb) == 0)
|
||||||
{
|
{
|
||||||
if (errno == EEXIST)
|
fpid = fopen(pluto_lock, "r");
|
||||||
|
if (fpid)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "pluto: lock file \"%s\" already exists\n"
|
char buf[64];
|
||||||
, pluto_lock);
|
pid_t pid = 0;
|
||||||
exit_pluto(10);
|
|
||||||
}
|
memset(buf, 0, sizeof(buf));
|
||||||
else
|
if (fread(buf, 1, sizeof(buf), fpid))
|
||||||
{
|
{
|
||||||
fprintf(stderr
|
buf[sizeof(buf) - 1] = '\0';
|
||||||
, "pluto: unable to create lock file \"%s\" (%d %s)\n"
|
pid = atoi(buf);
|
||||||
, pluto_lock, errno, strerror(errno));
|
}
|
||||||
exit_pluto(1);
|
fclose(fpid);
|
||||||
|
if (pid && kill(pid, 0) == 0)
|
||||||
|
{ /* such a process is running */
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
fprintf(stderr, "pluto: removing lock file \"%s\", process not "
|
||||||
|
"running\n", pluto_lock);
|
||||||
|
unlink(pluto_lock);
|
||||||
}
|
}
|
||||||
pluto_lock_created = TRUE;
|
pluto_lock_checked = TRUE;
|
||||||
return fd;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool fill_lock(int lockfd, pid_t pid)
|
static void fill_lock(void)
|
||||||
{
|
{
|
||||||
char buf[30]; /* holds "<pid>\n" */
|
pidfile = fopen(pluto_lock, "w");
|
||||||
int len = snprintf(buf, sizeof(buf), "%u\n", (unsigned int) pid);
|
if (pidfile)
|
||||||
bool ok = len > 0 && write(lockfd, buf, len) == len;
|
{
|
||||||
|
fprintf(pidfile, "%u\n", (u_int)getpid());
|
||||||
close(lockfd);
|
fflush(pidfile);
|
||||||
return ok;
|
}
|
||||||
|
/* keep pidfile open so we can truncate it, if we cannot delete it */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void delete_lock(void)
|
static void delete_lock(void)
|
||||||
{
|
{
|
||||||
if (pluto_lock_created)
|
/* because unlinking the PID file may fail, we truncate it to ensure the
|
||||||
|
* daemon can be properly restarted. one probable cause for this is the
|
||||||
|
* combination of not running as root and the effective user lacking
|
||||||
|
* permissions on the parent dir(s) of the PID file */
|
||||||
|
if (pluto_lock_checked)
|
||||||
{
|
{
|
||||||
|
if (pidfile)
|
||||||
|
{
|
||||||
|
ignore_result(ftruncate(fileno(pidfile), 0));
|
||||||
|
fclose(pidfile);
|
||||||
|
}
|
||||||
|
unlink(pluto_lock);
|
||||||
|
/* delete this here to avoid that exit_pluto calls delete the socket */
|
||||||
delete_ctl_socket();
|
delete_ctl_socket();
|
||||||
unlink(pluto_lock); /* is noting failure useful? */
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -263,7 +288,6 @@ int main(int argc, char **argv)
|
|||||||
unsigned int keep_alive = 0;
|
unsigned int keep_alive = 0;
|
||||||
bool force_keepalive = FALSE;
|
bool force_keepalive = FALSE;
|
||||||
char *virtual_private = NULL;
|
char *virtual_private = NULL;
|
||||||
int lockfd;
|
|
||||||
#ifdef CAPABILITIES
|
#ifdef CAPABILITIES
|
||||||
int keep[] = { CAP_NET_ADMIN, CAP_NET_BIND_SERVICE };
|
int keep[] = { CAP_NET_ADMIN, CAP_NET_BIND_SERVICE };
|
||||||
#endif /* CAPABILITIES */
|
#endif /* CAPABILITIES */
|
||||||
@@ -545,7 +569,12 @@ int main(int argc, char **argv)
|
|||||||
if (optind != argc)
|
if (optind != argc)
|
||||||
usage("unexpected argument");
|
usage("unexpected argument");
|
||||||
reset_debugging();
|
reset_debugging();
|
||||||
lockfd = create_lock();
|
|
||||||
|
if (check_lock())
|
||||||
|
{
|
||||||
|
fprintf(stderr, "pluto: lock file \"%s\" already exists\n", pluto_lock);
|
||||||
|
exit_pluto(10);
|
||||||
|
}
|
||||||
|
|
||||||
/* select between logging methods */
|
/* select between logging methods */
|
||||||
|
|
||||||
@@ -598,11 +627,13 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
if (pid != 0)
|
if (pid != 0)
|
||||||
{
|
{
|
||||||
/* parent: die, after filling PID into lock file.
|
/* parent: die
|
||||||
* must not use exit_pluto: lock would be removed!
|
* must not use exit_pluto: lock would be removed!
|
||||||
*/
|
*/
|
||||||
exit(fill_lock(lockfd, pid)? 0 : 1);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
/* child: fill PID into lock file */
|
||||||
|
fill_lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setsid() < 0)
|
if (setsid() < 0)
|
||||||
@@ -617,7 +648,7 @@ int main(int argc, char **argv)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* no daemon fork: we have to fill in lock file */
|
/* no daemon fork: we have to fill in lock file */
|
||||||
(void) fill_lock(lockfd, getpid());
|
fill_lock();
|
||||||
fprintf(stdout, "Pluto initialized\n");
|
fprintf(stdout, "Pluto initialized\n");
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user