noinst_LIBRARIES = librngd.a
rngd_SOURCES = rngd.h rngd.c rngd_entsource.h rngd_entsource.c \
- rngd_linux.h rngd_linux.c
+ rngd_linux.h rngd_linux.c util.c
rngd_LDADD = librngd.a
rngtest_SOURCES = exits.h stats.h stats.c rngtest.c
[\fB\-b\fR, \fB\-\-background\fR]
[\fB\-f\fR, \fB\-\-foreground\fR]
[\fB\-o\fR, \fB\-\-random-device=\fIfile\fR]
+[\fB\-p\fR, \fB\-\-pid-file=\fIfile\fR]
[\fB\-r\fR, \fB\-\-rng-device=\fIfile\fR]
[\fB\-s\fR, \fB\-\-random-step=\fInnn\fR]
[\fB\-W\fR, \fB\-\-fill-watermark=\fInnn\fR]
\fB\-f\fR, \fB\-\-foreground\fR
Do not fork and become a daemon
.TP
+\fB\-p\fI file\fR, \fB\-\-pid-file=\fIfile\fR
+File used for recording daemon PID, and multiple exclusion
+(default: /var/run/rngd.pid)
+.TP
\fB\-o\fI file\fR, \fB\-\-random-device=\fIfile\fR
Kernel device used for random number output
(default: /dev/random)
#include <string.h>
#include <argp.h>
#include <syslog.h>
+#include <signal.h>
#include "rngd.h"
#include "fips.h"
/* Background/daemon mode */
int am_daemon; /* Nonzero if we went daemon */
+bool server_running = true; /* set to false, to stop daemon */
+
/* Command line arguments and processing */
const char *argp_program_version =
"rngd " VERSION "\n"
{ "rng-device", 'r', "file", 0,
"Kernel device used for random number input (default: /dev/hw_random)" },
+ { "pid-file", 'p', "file", 0,
+ "File used for recording daemon PID, and multiple exclusion (default: /var/run/rngd.pid)" },
+
{ "random-step", 's', "nnn", 0,
"Number of bytes written to random-device at a time (default: 64)" },
static struct arguments default_arguments = {
.random_name = "/dev/random",
+ .pid_file = "/var/run/rngd.pid",
.poll_timeout = 60,
.random_step = 64,
.fill_watermark = 2048,
case 'o':
arguments->random_name = arg;
break;
+ case 'p':
+ arguments->pid_file = arg;
+ break;
case 'r':
rng_default.rng_name = arg;
break;
{
int rc;
+ if (!server_running)
+ return;
+
if (iter->disabled)
continue; /* failed, no work */
"No entropy sources working, exiting rngd\n");
}
+static void term_signal(int signo)
+{
+ server_running = false;
+}
+
int main(int argc, char **argv)
{
int rc_rng = 0;
int rc_tpm = 0;
+ int pid_fd = -1;
openlog("rngd", 0, LOG_DAEMON);
}
return 1;
}
-
+
if (arguments->verbose) {
printf("Available entropy sources:\n");
if (!rc_rng)
printf("\tTPM\n");
}
- if (rc_rng
+ if (rc_rng
&& (rc_tpm || !arguments->enable_tpm)) {
if (!arguments->quiet)
message(LOG_DAEMON|LOG_ERR,
strerror(errno));
return 1;
}
+
+ /* require valid, locked PID file to proceed */
+ pid_fd = write_pid_file(arguments->pid_file);
+ if (pid_fd < 0)
+ return 1;
+
+ signal(SIGHUP, SIG_IGN);
+ signal(SIGPIPE, SIG_IGN);
+ signal(SIGINT, term_signal);
+ signal(SIGTERM, term_signal);
}
do_loop(arguments->random_step,
arguments->poll_timeout ? : -1.0);
+ if (pid_fd >= 0)
+ unlink(arguments->pid_file);
+
return 0;
}
/* Command line arguments and processing */
struct arguments {
char *random_name;
+ char *pid_file;
int random_step;
int fill_watermark;
} while (0)
extern void src_list_add(struct rng *ent_src);
+extern int write_pid_file(const char *pid_fn);
#endif /* RNGD__H */
--- /dev/null
+
+/*
+ * Copyright 2009 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#define _GNU_SOURCE
+
+#ifndef HAVE_CONFIG_H
+#error Invalid or missing autoconf build environment
+#endif
+
+#include "rng-tools-config.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+
+#include "rngd.h"
+
+int write_pid_file(const char *pid_fn)
+{
+ char str[32], *s;
+ size_t bytes;
+ int fd;
+ struct flock lock;
+ int err;
+
+ /* build file data */
+ sprintf(str, "%u\n", (unsigned int) getpid());
+
+ /* open non-exclusively (works on NFS v2) */
+ fd = open(pid_fn, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
+ if (fd < 0) {
+ err = errno;
+
+ message(LOG_DAEMON|LOG_ERR, "Cannot open PID file %s: %s",
+ pid_fn, strerror(err));
+ return -err;
+ }
+
+ /* lock */
+ memset(&lock, 0, sizeof(lock));
+ lock.l_type = F_WRLCK;
+ lock.l_whence = SEEK_SET;
+ if (fcntl(fd, F_SETLK, &lock) != 0) {
+ err = errno;
+ if (err == EAGAIN) {
+ message(LOG_DAEMON|LOG_ERR, "PID file %s is already locked",
+ pid_fn);
+ } else {
+ message(LOG_DAEMON|LOG_ERR, "Cannot lock PID file %s: %s",
+ pid_fn, strerror(err));
+ }
+ close(fd);
+ return -err;
+ }
+
+ /* write file data */
+ bytes = strlen(str);
+ s = str;
+ while (bytes > 0) {
+ ssize_t rc = write(fd, s, bytes);
+ if (rc < 0) {
+ err = errno;
+ message(LOG_DAEMON|LOG_ERR, "PID number write failed: %s",
+ strerror(err));
+ goto err_out;
+ }
+
+ bytes -= rc;
+ s += rc;
+ }
+
+ /* make sure file data is written to disk */
+ if (fsync(fd) < 0) {
+ err = errno;
+ message(LOG_DAEMON|LOG_ERR, "PID file fsync failed: %s", strerror(err));
+ goto err_out;
+ }
+
+ return fd;
+
+err_out:
+ unlink(pid_fn);
+ close(fd);
+ return -err;
+}
+