aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile3
-rw-r--r--log.c4
-rw-r--r--log.h2
-rw-r--r--pingu.c29
-rw-r--r--pingu_adm.c135
-rw-r--r--pingu_adm.h12
-rw-r--r--pingu_host.c11
-rw-r--r--pingu_host.h1
8 files changed, 182 insertions, 15 deletions
diff --git a/Makefile b/Makefile
index c993407..d9d73be 100644
--- a/Makefile
+++ b/Makefile
@@ -17,6 +17,7 @@ pingu_OBJS = \
icmp.o \
log.o \
pingu.o \
+ pingu_adm.o \
pingu_burst.o \
pingu_conf.o \
pingu_gateway.o \
@@ -46,6 +47,6 @@ mtu: $(mtu_OBJS)
install: $(TARGETS)
$(INSTALLDIR) $(DESTDIR)/$(BINDIR)
$(INSTALL) $(TARGETS) $(DESTDIR)/$(BINDIR)
-
+
clean:
rm -f $(TARGETS) $(ALL_OBJS)
diff --git a/log.c b/log.c
index 4bc770b..85a32e6 100644
--- a/log.c
+++ b/log.c
@@ -22,10 +22,10 @@
static int log_verbose = 0;
-void log_init(int verbose)
+void log_init(const char* prefix, int verbose)
{
log_verbose = verbose;
- openlog("pingu", LOG_PERROR | LOG_PID, LOG_DAEMON);
+ openlog(prefix, LOG_PERROR | LOG_PID, LOG_DAEMON);
}
void log_debug(const char *format, ...)
diff --git a/log.h b/log.h
index ef6155d..a7d4688 100644
--- a/log.h
+++ b/log.h
@@ -1,6 +1,6 @@
#ifndef LOG_H
#define LOG_H
-void log_init(int verbose);
+void log_init(const char* prefix, int verbose);
void log_debug(const char *format, ...);
void log_perror(const char *message);
void log_error(const char *format, ...);
diff --git a/pingu.c b/pingu.c
index 0cd59b8..7d5aed4 100644
--- a/pingu.c
+++ b/pingu.c
@@ -14,6 +14,7 @@
#include "log.h"
+#include "pingu_adm.h"
#include "pingu_conf.h"
#include "pingu_host.h"
#include "pingu_iface.h"
@@ -24,7 +25,7 @@
#endif
#ifndef DEFAULT_PIDFILE
-#define DEFAULT_PIDFILE "/var/run/pingu.pid"
+#define DEFAULT_PIDFILE "/var/run/pingu/pingu.pid"
#endif
int pingu_verbose = 0, pid_file_fd = 0, pingu_daemonize = 0;
@@ -40,11 +41,11 @@ int usage(const char *program)
print_version(program);
fprintf(stderr, "usage: %s [-dh] [-c CONFIG] [-p PIDFILE]\n"
"options:\n"
- " -c Read configuration from FILE (default is "
+ " -c Read configuration from FILE (default is "
DEFAULT_CONFIG ")\n"
" -d Fork to background (damonize)\n"
" -h Show this help\n"
- " -p Use PIDFILE as pidfile (default is "
+ " -p Use PIDFILE as pidfile (default is "
DEFAULT_PIDFILE ")\n"
" -V Print version and exit\n"
"\n",
@@ -119,12 +120,16 @@ int main(int argc, char *argv[])
{
int c;
const char *config_file = DEFAULT_CONFIG;
+ const char *adm_socket = DEFAULT_ADM_SOCKET;
int verbose = 0;
static struct ev_loop *loop;
static struct ev_signal signal_watcher;
- while ((c = getopt(argc, argv, "c:dhp:Vv")) != -1) {
+ while ((c = getopt(argc, argv, "a:c:dhp:Vv")) != -1) {
switch (c) {
+ case 'a':
+ adm_socket = optarg;
+ break;
case 'c':
config_file = optarg;
break;
@@ -148,30 +153,32 @@ int main(int argc, char *argv[])
argc -= optind;
argv += optind;
- log_init(verbose);
+ log_init("pingu", verbose);
loop = ev_default_loop(0);
-
+
if (pingu_conf_parse(config_file) < 0)
return 1;
-
+
if (pingu_iface_init(loop) < 0)
return 1;
-
+
if (pingu_host_init(loop) < 0)
return 1;
-
- kernel_init(loop);
+
+ if (pingu_adm_init(loop, adm_socket) < 0)
+ return 1;
if (pingu_daemonize) {
if (daemonize() == -1)
return 1;
}
+ kernel_init(loop);
ev_signal_init(&signal_watcher, sigint_cb, SIGINT);
ev_signal_start(loop, &signal_watcher);
ev_run(loop, 0);
-
+ log_info("Shutting down");
pingu_iface_cleanup();
kernel_close();
return 0;
diff --git a/pingu_adm.c b/pingu_adm.c
new file mode 100644
index 0000000..d5c25a9
--- /dev/null
+++ b/pingu_adm.c
@@ -0,0 +1,135 @@
+
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <ev.h>
+
+#include "list.h"
+#include "log.h"
+#include "pingu_adm.h"
+#include "pingu_host.h"
+
+static struct ev_io accept_io;
+
+struct adm_conn {
+ struct ev_io io;
+ struct ev_timer timeout;
+ int num_read;
+ char cmd[512];
+};
+
+static void pingu_adm_free_conn(struct ev_loop *loop, struct adm_conn *rm)
+{
+ int fd = rm->io.fd;
+
+ ev_io_stop(loop, &rm->io);
+ ev_timer_stop(loop, &rm->timeout);
+ close(fd);
+ free(rm);
+}
+
+static void pingu_adm_recv_cb (struct ev_loop *loop, struct ev_io *w,
+ int revents)
+{
+ struct adm_conn *conn = container_of(w, struct adm_conn, io);
+ int len;
+
+ len = recv(conn->io.fd, conn->cmd, sizeof(conn->cmd) - conn->num_read,
+ MSG_DONTWAIT);
+ if (len < 0 && errno == EAGAIN)
+ return;
+ if (len <= 0)
+ goto err;
+
+ conn->num_read += len;
+ if (conn->num_read >= sizeof(conn->cmd))
+ goto err;
+ if (conn->cmd[conn->num_read - 1] != '\n')
+ goto err;
+
+ conn->num_read--;
+ conn->cmd[conn->num_read] = '\0';
+
+ if (strncmp(conn->cmd, "status", len) == 0) {
+ pingu_host_dump_status(conn->io.fd);
+ conn->cmd[0] = '\0';
+ conn->num_read = 0;
+ } else {
+ log_error("unknown adm command");
+ }
+ return;
+
+err:
+ pingu_adm_free_conn(loop, conn);
+}
+
+static void pingu_adm_timeout_cb (struct ev_loop *loop, struct ev_timer *t,
+ int revents)
+{
+ log_debug("adm connection timed out");
+ pingu_adm_free_conn(loop, container_of(t, struct adm_conn, timeout));
+}
+
+static void pingu_adm_accept_cb(struct ev_loop *loop, struct ev_io *w,
+ int revents)
+{
+ struct adm_conn *conn;
+ struct sockaddr_storage from;
+ socklen_t fromlen = sizeof(from);
+ int fd;
+
+ fd = accept(w->fd, (struct sockaddr *) &from, &fromlen);
+ if (fd < 0) {
+ log_perror("accept");
+ return;
+ }
+
+ fcntl(fd, F_SETFD, FD_CLOEXEC);
+ conn = calloc(1, sizeof(struct adm_conn));
+
+ ev_io_init(&conn->io, pingu_adm_recv_cb, fd, EV_READ);
+ ev_io_start(loop, &conn->io);
+ ev_timer_init(&conn->timeout, pingu_adm_timeout_cb, 10.0, 0.);
+ ev_timer_start(loop, &conn->timeout);
+}
+
+
+int pingu_adm_init(struct ev_loop *loop, const char *socket_path)
+{
+ struct sockaddr_un sun;
+ int fd;
+
+ memset(&sun, 0, sizeof(sun));
+ sun.sun_family = AF_UNIX;
+ strncpy(sun.sun_path, socket_path, sizeof(sun.sun_path));
+
+ fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (fd < 0) {
+ log_perror("socket");
+ return -1;
+ }
+
+ fcntl(fd, F_SETFD, FD_CLOEXEC);
+ unlink(socket_path);
+ if (bind(fd, (struct sockaddr *) &sun, sizeof(sun)) < 0)
+ goto perr_close;
+
+ if (listen(fd, 5) < 0)
+ goto perr_close;
+
+ ev_io_init(&accept_io, pingu_adm_accept_cb, fd, EV_READ);
+ ev_io_start(loop, &accept_io);
+ return 0;
+
+perr_close:
+ log_perror(socket_path);
+ close(fd);
+ return -1;
+
+}
diff --git a/pingu_adm.h b/pingu_adm.h
new file mode 100644
index 0000000..3b50b06
--- /dev/null
+++ b/pingu_adm.h
@@ -0,0 +1,12 @@
+#ifndef PINGU_ADM_H
+#define PINGU_ADM_H
+
+#include <ev.h>
+
+#ifndef DEFAULT_ADM_SOCKET
+#define DEFAULT_ADM_SOCKET "/var/run/pingu/pingu.ctl"
+#endif
+
+int pingu_adm_init(struct ev_loop *loop, const char *socket_path);
+
+#endif
diff --git a/pingu_host.c b/pingu_host.c
index 5fa5aaf..5146f51 100644
--- a/pingu_host.c
+++ b/pingu_host.c
@@ -111,6 +111,17 @@ struct pingu_host *pingu_host_find_by_iface(struct pingu_iface *iface)
return NULL;
}
+void pingu_host_dump_status(int fd)
+{
+ struct pingu_host *host;
+ char buf[512];
+ list_for_each_entry(host, &host_list, host_list_entry) {
+ snprintf(buf, sizeof(buf), "%s: %i\n", host->label, host->status);
+ write(fd, buf, strlen(buf));
+ }
+ write(fd, "", 1);
+}
+
int pingu_host_init(struct ev_loop *loop)
{
struct pingu_host *host;
diff --git a/pingu_host.h b/pingu_host.h
index 78afbaf..b5f6e48 100644
--- a/pingu_host.h
+++ b/pingu_host.h
@@ -37,5 +37,6 @@ struct pingu_host *pingu_host_find_by_iface(struct pingu_iface *iface);
int pingu_host_set_status(struct pingu_host *host, int status);
int pingu_host_init(struct ev_loop *loop);
int pingu_host_verify_status(struct ev_loop *loop, struct pingu_host *host);
+void pingu_host_dump_status(int fd);
#endif