summaryrefslogtreecommitdiffstats
path: root/daemon/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'daemon/main.c')
-rw-r--r--daemon/main.c198
1 files changed, 198 insertions, 0 deletions
diff --git a/daemon/main.c b/daemon/main.c
new file mode 100644
index 0000000..253bf35
--- /dev/null
+++ b/daemon/main.c
@@ -0,0 +1,198 @@
+#define _GNU_SOURCE
+
+#include <signal.h>
+#include <grp.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include <daemon-log.h>
+#include <daemon-signal.h>
+#include <daemon-fork.h>
+#include <daemon-pid.h>
+
+#include <config.h>
+
+#include "common.h"
+#include "main.h"
+#include "ipqapi.h"
+#include "client.h"
+#include "icmp.h"
+#include "packet.h"
+
+gboolean opt_fork = TRUE;
+gboolean opt_syslog = TRUE;
+
+fd_set listen_wfds, listen_rfds, select_wfds, select_rfds;
+
+gboolean fail = FALSE;
+
+guint32 default_verdict = 15; // ICMP packet filtered
+//guint32 default_verdict = 1; // Accept
+
+gboolean log_packets = FALSE;
+
+static gboolean _verdict_func(ipq_packet_msg_t*m) {
+ if (log_packets)
+ daemon_log(LOG_DEBUG, "[%lu] Still unanswered, verdicting", m->packet_id);
+ ipqapi_verdict(m, default_verdict);
+ return FALSE;
+}
+
+int init() {
+ if (daemon_signal_init(SIGPIPE, SIGUSR1, SIGUSR2, SIGHUP, SIGINT, SIGQUIT, SIGTERM, -1) < 0)
+ return -1;
+
+ FD_ZERO(&listen_wfds);
+ FD_ZERO(&listen_rfds);
+
+ if (ipqapi_init() < 0)
+ return -1;
+
+ if (client_init() < 0 )
+ return -1;
+
+ if (icmp_init() < 0)
+ return -1;
+
+ return 0;
+}
+
+void done() {
+ ipqapi_done();
+ client_done();
+ icmp_done();
+ packets_free();
+ daemon_signal_done();
+}
+
+int loop() {
+ int r;
+
+ daemon_log(LOG_INFO, "%s "VERSION" sucessfully initialized.", daemon_log_ident);
+
+ while (!fail) {
+ int sig;
+
+ select_rfds = listen_rfds;
+ select_wfds = listen_wfds;
+
+ if (select(FD_SETSIZE, &select_rfds, &select_wfds, NULL, NULL) < 0 && errno != EINTR) {
+ daemon_log(LOG_ERR, "select: %s", strerror(errno));
+ goto finish;
+ }
+
+ if ((sig = daemon_signal_next()) >= 0) {
+
+ switch (sig) {
+ case SIGINT:
+ case SIGQUIT:
+ case SIGTERM:
+ daemon_log(LOG_INFO, "Recieved signal <%s>, exiting cleanly", strsignal(sig));
+ r = 0;
+ goto finish;
+
+ case SIGHUP:
+ daemon_log(LOG_INFO, "Recieved signal <%s>, reporting status info:", strsignal(sig));
+ daemon_log(LOG_INFO, "%u packets total, %u packets in queue", get_total_packets(), get_queued_packets());
+ break;
+
+ case SIGUSR1:
+ case SIGUSR2:
+ log_packets = sig == SIGUSR1;
+ daemon_log(LOG_INFO, "Recieved signal <%s>, %s packet logging", strsignal(sig), log_packets ? "enabling" : "disabling");
+ break;
+
+ case SIGPIPE:
+ break;
+
+ default:
+ daemon_log(LOG_WARNING, "Recieved signal <%s>, ignoring.", strsignal(sig));
+ }
+
+ } else {
+ if (client_work() < 0)
+ goto finish;
+
+ if (ipqapi_work() < 0)
+ goto finish;
+ }
+
+ packet_foreach(client_is_connected(), _verdict_func);
+ }
+
+ r = 0;
+
+finish:
+
+ daemon_log(LOG_INFO, "%s exiting.", daemon_log_ident);
+
+ return r;
+}
+
+
+int start() {
+ struct group *gr;
+ setuid(geteuid());
+
+ if (!(gr = getgrnam("fieryfilter"))) {
+ daemon_log(LOG_ERR, "Could not find group fieryfilter");
+ return 1;
+ }
+
+ if (setgid(gr->gr_gid) != 0) {
+ daemon_log(LOG_ERR, "setgid(): %s", strerror(errno));
+ return 1;
+ }
+
+ if (opt_fork) {
+ pid_t pid;
+
+ daemon_retval_init();
+
+ if ((pid = daemon_fork()) < 0)
+ return 1;
+ else if (pid != 0) {
+ int r = daemon_retval_wait(10);
+ return r < 0 ? 1 : r;
+ } else {
+ daemon_log_use_syslog = opt_syslog;
+
+ if (init() < 0) {
+ daemon_retval_send(1);
+ done();
+ return 1;
+ }
+
+ daemon_retval_send(0);
+ }
+ } else {
+ daemon_log_use_syslog = opt_syslog;
+
+ if (init() < 0) {
+ done();
+ return 1;
+ }
+ }
+
+
+ if (loop() < 0) {
+ done();
+ return 1;
+ }
+
+ done();
+ return 0;
+
+}
+
+int main(int argc, char *argv[]) {
+ if ((daemon_log_ident = strrchr(argv[0], '/')))
+ daemon_log_ident++;
+ else
+ daemon_log_ident = argv[0];
+
+ daemon_log_use_syslog = FALSE;
+
+ return start();
+}