|
|
5481a5 |
diff --git a/radvd.c b/radvd.c
|
|
|
5481a5 |
index 82efe0b..508abd1 100644
|
|
|
5481a5 |
--- a/radvd.c
|
|
|
5481a5 |
+++ b/radvd.c
|
|
|
5481a5 |
@@ -17,6 +17,10 @@
|
|
|
5481a5 |
#include "includes.h"
|
|
|
5481a5 |
#include "radvd.h"
|
|
|
5481a5 |
#include "pathnames.h"
|
|
|
5481a5 |
+#include <libgen.h>
|
|
|
5481a5 |
+#include <sys/file.h>
|
|
|
5481a5 |
+#include <stdio.h>
|
|
|
5481a5 |
+
|
|
|
5481a5 |
|
|
|
5481a5 |
#ifdef HAVE_NETLINK
|
|
|
5481a5 |
#include "netlink.h"
|
|
|
5481a5 |
@@ -99,6 +103,9 @@ int readin_config(char *);
|
|
|
5481a5 |
int check_conffile_perm(const char *, const char *);
|
|
|
5481a5 |
const char *get_pidfile(void);
|
|
|
5481a5 |
void main_loop(void);
|
|
|
5481a5 |
+static int write_pid_file(char const *daemon_pid_file_ident, pid_t pid);
|
|
|
5481a5 |
+static int open_and_lock_pid_file(char const *daemon_pid_file_ident);
|
|
|
5481a5 |
+static void check_pid_file(char const *daemon_pid_file_ident);
|
|
|
5481a5 |
|
|
|
5481a5 |
int
|
|
|
5481a5 |
main(int argc, char *argv[])
|
|
|
5481a5 |
@@ -110,6 +117,7 @@ main(int argc, char *argv[])
|
|
|
5481a5 |
char *chrootdir = NULL;
|
|
|
5481a5 |
int configtest = 0;
|
|
|
5481a5 |
int daemonize = 1;
|
|
|
5481a5 |
+ int pidfd = 0;
|
|
|
5481a5 |
#ifdef HAVE_GETOPT_LONG
|
|
|
5481a5 |
int opt_idx;
|
|
|
5481a5 |
#endif
|
|
|
5481a5 |
@@ -332,6 +340,14 @@ main(int argc, char *argv[])
|
|
|
5481a5 |
exit(1);
|
|
|
5481a5 |
}
|
|
|
5481a5 |
daemon_retval_send(0);
|
|
|
5481a5 |
+ } else {
|
|
|
5481a5 |
+ pidfd = open_and_lock_pid_file(pidfile);
|
|
|
5481a5 |
+ if (0 != write_pid_file(pidfile, getpid())) {
|
|
|
5481a5 |
+ flog(LOG_ERR, "failure writing pid file detected");
|
|
|
5481a5 |
+ exit(-1);
|
|
|
5481a5 |
+ }
|
|
|
5481a5 |
+ check_pid_file(pidfile);
|
|
|
5481a5 |
+
|
|
|
5481a5 |
}
|
|
|
5481a5 |
|
|
|
5481a5 |
/*
|
|
|
5481a5 |
@@ -347,11 +363,11 @@ main(int argc, char *argv[])
|
|
|
5481a5 |
main_loop();
|
|
|
5481a5 |
flog(LOG_INFO, "sending stop adverts", pidfile);
|
|
|
5481a5 |
stop_adverts();
|
|
|
5481a5 |
- if (daemonize) {
|
|
|
5481a5 |
- flog(LOG_INFO, "removing %s", pidfile);
|
|
|
5481a5 |
- unlink(pidfile);
|
|
|
5481a5 |
+ if (!daemonize){
|
|
|
5481a5 |
+ close(pidfd);
|
|
|
5481a5 |
}
|
|
|
5481a5 |
-
|
|
|
5481a5 |
+ flog(LOG_INFO, "removing %s", pidfile);
|
|
|
5481a5 |
+ unlink(pidfile);
|
|
|
5481a5 |
return 0;
|
|
|
5481a5 |
}
|
|
|
5481a5 |
|
|
|
5481a5 |
@@ -841,3 +857,105 @@ usage(void)
|
|
|
5481a5 |
exit(1);
|
|
|
5481a5 |
}
|
|
|
5481a5 |
|
|
|
5481a5 |
+static int open_pid_file(char const *daemon_pid_file_ident)
|
|
|
5481a5 |
+{
|
|
|
5481a5 |
+ int pidfd = open(daemon_pid_file_ident, O_SYNC | O_CREAT | O_RDWR, 0644);
|
|
|
5481a5 |
+ if (-1 == pidfd) {
|
|
|
5481a5 |
+ flog(LOG_ERR, "unable to open pid file, %s: %s", daemon_pid_file_ident, strerror(errno));
|
|
|
5481a5 |
+ exit(-1);
|
|
|
5481a5 |
+ } else {
|
|
|
5481a5 |
+ dlog(LOG_DEBUG, 5, "opened pid file %s", daemon_pid_file_ident);
|
|
|
5481a5 |
+ }
|
|
|
5481a5 |
+ return pidfd;
|
|
|
5481a5 |
+}
|
|
|
5481a5 |
+
|
|
|
5481a5 |
+static int open_and_lock_pid_file(char const *daemon_pid_file_ident)
|
|
|
5481a5 |
+{
|
|
|
5481a5 |
+ dlog(LOG_DEBUG, 3, "radvd startup PID is %d", getpid());
|
|
|
5481a5 |
+
|
|
|
5481a5 |
+ int pidfd = open_pid_file(daemon_pid_file_ident);
|
|
|
5481a5 |
+
|
|
|
5481a5 |
+ int lock = flock(pidfd, LOCK_EX | LOCK_NB);
|
|
|
5481a5 |
+ if (0 != lock) {
|
|
|
5481a5 |
+ flog(LOG_ERR, "unable to lock pid file, %s: %s", daemon_pid_file_ident, strerror(errno));
|
|
|
5481a5 |
+ exit(-1);
|
|
|
5481a5 |
+ } else {
|
|
|
5481a5 |
+ dlog(LOG_DEBUG, 4, "locked pid file %s", daemon_pid_file_ident);
|
|
|
5481a5 |
+ }
|
|
|
5481a5 |
+
|
|
|
5481a5 |
+ return pidfd;
|
|
|
5481a5 |
+}
|
|
|
5481a5 |
+
|
|
|
5481a5 |
+
|
|
|
5481a5 |
+static int write_pid_file(char const *daemon_pid_file_ident, pid_t pid)
|
|
|
5481a5 |
+{
|
|
|
5481a5 |
+ int pidfd = open_pid_file(daemon_pid_file_ident);
|
|
|
5481a5 |
+ char pid_str[20] = {""};
|
|
|
5481a5 |
+ sprintf(pid_str, "%d", pid);
|
|
|
5481a5 |
+ dlog(LOG_DEBUG, 3, "radvd PID is %s", pid_str);
|
|
|
5481a5 |
+ size_t len = strlen(pid_str);
|
|
|
5481a5 |
+ int rc = write(pidfd, pid_str, len);
|
|
|
5481a5 |
+ if (rc != (int)len) {
|
|
|
5481a5 |
+ return -1;
|
|
|
5481a5 |
+ }
|
|
|
5481a5 |
+ char newline[] = {"\n"};
|
|
|
5481a5 |
+ len = strlen(newline);
|
|
|
5481a5 |
+ rc = write(pidfd, newline, len);
|
|
|
5481a5 |
+ if (rc != (int)len) {
|
|
|
5481a5 |
+ close(pidfd);
|
|
|
5481a5 |
+ return -1;
|
|
|
5481a5 |
+ }
|
|
|
5481a5 |
+ rc = fsync(pidfd);
|
|
|
5481a5 |
+ if (rc != 0) {
|
|
|
5481a5 |
+ dlog(LOG_DEBUG, 4, "failed to fsync pid file: %s", daemon_pid_file_ident);
|
|
|
5481a5 |
+ }
|
|
|
5481a5 |
+ rc = close(pidfd);
|
|
|
5481a5 |
+ if (rc != 0) {
|
|
|
5481a5 |
+ dlog(LOG_DEBUG, 4, "failed to close pid file: %s", daemon_pid_file_ident);
|
|
|
5481a5 |
+ }
|
|
|
5481a5 |
+ char *dirstrcopy = strdup(daemon_pid_file_ident);
|
|
|
5481a5 |
+ char *dirstr = dirname(dirstrcopy);
|
|
|
5481a5 |
+ int dirfd = open(dirstr, O_RDONLY);
|
|
|
5481a5 |
+ if (dirfd == -1){
|
|
|
5481a5 |
+ dlog(LOG_DEBUG, 4, "Failed to open directory: %s", dirstr);
|
|
|
5481a5 |
+ }
|
|
|
5481a5 |
+ rc = fsync(dirfd);
|
|
|
5481a5 |
+ if (rc != 0) {
|
|
|
5481a5 |
+ dlog(LOG_DEBUG, 4, "failed to fsync pid dir: %s", dirstr);
|
|
|
5481a5 |
+ }
|
|
|
5481a5 |
+ rc = close(dirfd);
|
|
|
5481a5 |
+ if (rc != 0) {
|
|
|
5481a5 |
+ dlog(LOG_DEBUG, 4, "failed to close pid dir: %s", dirstr);
|
|
|
5481a5 |
+ }
|
|
|
5481a5 |
+ free(dirstrcopy);
|
|
|
5481a5 |
+ dlog(LOG_DEBUG, 4, "wrote pid %d to pid file: %s", pid, daemon_pid_file_ident);
|
|
|
5481a5 |
+ return rc;
|
|
|
5481a5 |
+}
|
|
|
5481a5 |
+
|
|
|
5481a5 |
+
|
|
|
5481a5 |
+static void check_pid_file(char const *daemon_pid_file_ident)
|
|
|
5481a5 |
+{
|
|
|
5481a5 |
+ FILE *pidfile = fopen(daemon_pid_file_ident, "r");
|
|
|
5481a5 |
+
|
|
|
5481a5 |
+ if (!pidfile) {
|
|
|
5481a5 |
+ flog(LOG_ERR, "unable to open pid file, %s: %s", daemon_pid_file_ident, strerror(errno));
|
|
|
5481a5 |
+ exit(-1);
|
|
|
5481a5 |
+ }
|
|
|
5481a5 |
+
|
|
|
5481a5 |
+ pid_t pid = -1;
|
|
|
5481a5 |
+
|
|
|
5481a5 |
+ int rc = fscanf(pidfile, "%d", &pid;;
|
|
|
5481a5 |
+ fclose(pidfile);
|
|
|
5481a5 |
+
|
|
|
5481a5 |
+ if (rc != 1) {
|
|
|
5481a5 |
+ flog(LOG_ERR, "unable to read pid from pid file: %s", daemon_pid_file_ident);
|
|
|
5481a5 |
+ exit(-1);
|
|
|
5481a5 |
+ }
|
|
|
5481a5 |
+
|
|
|
5481a5 |
+ if (pid != getpid()) {
|
|
|
5481a5 |
+ flog(LOG_ERR, "pid in file, %s, doesn't match getpid(): %d != %d", daemon_pid_file_ident, pid, getpid());
|
|
|
5481a5 |
+ exit(-1);
|
|
|
5481a5 |
+ }
|
|
|
5481a5 |
+ dlog(LOG_DEBUG, 4, "validated pid file, %s: %d", daemon_pid_file_ident, pid);
|
|
|
5481a5 |
+}
|
|
|
5481a5 |
+
|