summaryrefslogtreecommitdiffstats
path: root/daemon/ipqapi.c
diff options
context:
space:
mode:
Diffstat (limited to 'daemon/ipqapi.c')
-rw-r--r--daemon/ipqapi.c118
1 files changed, 118 insertions, 0 deletions
diff --git a/daemon/ipqapi.c b/daemon/ipqapi.c
new file mode 100644
index 0000000..b0649bc
--- /dev/null
+++ b/daemon/ipqapi.c
@@ -0,0 +1,118 @@
+#include <string.h>
+#include <time.h>
+
+#include <daemon-log.h>
+
+#include "icmp.h"
+#include "ipqapi.h"
+#include "main.h"
+#include "client.h"
+#include "packet.h"
+
+#define BUFSIZE (10*1024)
+
+static struct ipq_handle *ipq = NULL;
+
+int ipqapi_init() {
+ int status;
+
+ if (!(ipq = ipq_create_handle(0, PF_INET))) {
+ daemon_log(LOG_ERR, "ipq_create_handle(): %s", ipq_errstr());
+ return -1;
+ }
+
+ if ((status = ipq_set_mode(ipq, IPQ_COPY_PACKET, BUFSIZE)) < 0) {
+ daemon_log(LOG_ERR, "ipq_set_mode(): %s", ipq_errstr());
+ daemon_log(LOG_INFO, "Perhaps you should run 'modprobe ip_queue'?");
+ ipq_destroy_handle(ipq);
+ ipq = NULL;
+ return -1;
+ }
+
+ FD_SET(ipq->fd, &listen_rfds);
+
+ return 0;
+}
+
+void ipqapi_done() {
+ if (ipq) {
+ FD_CLR(ipq->fd, &listen_rfds);
+ ipq_destroy_handle(ipq);
+ }
+
+ ipq = NULL;
+}
+
+int ipqapi_work() {
+ int status;
+ static guint8 buf[BUFSIZE];
+
+ if (!FD_ISSET(ipq->fd, &select_rfds))
+ return 0;
+
+ if ((status = ipq_read(ipq, buf, BUFSIZE, 0)) < 0) {
+ daemon_log(LOG_ERR, "ipq_read(): %s", ipq_errstr());
+ return -1;
+ }
+
+ switch (ipq_message_type(buf)) {
+ case NLMSG_ERROR:
+ daemon_log(LOG_ERR, "Received error message: %s\n", strerror(ipq_get_msgerr(buf)));
+ return -1;
+
+ case IPQM_PACKET: {
+ ipq_packet_msg_t *m = ipq_get_packet(buf);
+
+ if (!m->timestamp_sec)
+ time(&m->timestamp_sec);
+
+ if (log_packets)
+ daemon_log(LOG_DEBUG, "[%lu] Recieved packet, forwarding to client", m->packet_id);
+
+ if (client_is_connected()) {
+ packet_new(m);
+ client_send_enqueue(message_new(MSG_PACKET, (guint8*) m, sizeof(ipq_packet_msg_t)+m->data_len));
+ } else {
+ if (log_packets)
+ daemon_log(LOG_DEBUG, "[%lu] No clients listening, verdicting", m->packet_id);
+
+ if (ipqapi_verdict(m, default_verdict) < 0) {
+ daemon_log(LOG_ERR, "Sending verdict failed.");
+ return -1;
+ }
+ }
+
+ return 0;
+ }
+
+ default:
+ daemon_log(LOG_WARNING, "Recieved invalid IPQ message.");
+ return -1;
+ }
+}
+
+int ipqapi_verdict(ipq_packet_msg_t *m, guint32 resp) {
+ int nf = NF_DROP, icmp = 0;
+
+ if (resp > 17) resp = 17;
+
+ if (resp == 0)
+ nf = NF_DROP;
+ else if (resp == 1)
+ nf = NF_ACCEPT;
+ else {
+ nf = NF_DROP;
+ icmp = 1;
+ }
+
+ if (ipq_set_verdict(ipq, m->packet_id, nf, 0, NULL) < 0) {
+ daemon_log(LOG_ERR, "ipq_set_verdict(): %s", ipq_errstr());
+ return -1;
+ }
+
+
+ if (icmp)
+ return reply_icmp_error(m, resp-2);
+
+ return 0;
+}