#include #include #include #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; }