diff options
author | Natanael Copa <ncopa@alpinelinux.org> | 2011-09-21 15:26:36 +0200 |
---|---|---|
committer | Natanael Copa <ncopa@alpinelinux.org> | 2011-09-21 15:26:36 +0200 |
commit | 05ed02cf3a124e228480da65e09b88751c0859e6 (patch) | |
tree | 7662efb5c114d23a4eed255afbd40f49e90d037c | |
parent | 20cbd15c9eb521c6ca21d446b5cdf060df4eb169 (diff) | |
download | pingu-05ed02cf3a124e228480da65e09b88751c0859e6.tar.bz2 pingu-05ed02cf3a124e228480da65e09b88751c0859e6.tar.xz |
pingu_adm: implement initial admin socket
only supported command so far is "status"
-rw-r--r-- | Makefile | 3 | ||||
-rw-r--r-- | log.c | 4 | ||||
-rw-r--r-- | log.h | 2 | ||||
-rw-r--r-- | pingu.c | 29 | ||||
-rw-r--r-- | pingu_adm.c | 135 | ||||
-rw-r--r-- | pingu_adm.h | 12 | ||||
-rw-r--r-- | pingu_host.c | 11 | ||||
-rw-r--r-- | pingu_host.h | 1 |
8 files changed, 182 insertions, 15 deletions
@@ -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) @@ -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, ...) @@ -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, ...); @@ -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 |