#define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #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(); }