2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 * Author : Maxim Mamontov <faust@stargazer.dp.ua>
23 #include "stg/traffcounter.h"
24 #include "stg/plugin_creator.h"
25 #include "stg/common.h"
26 #include "stg/raw_ip_packet.h"
30 #include <linux/netfilter.h> /* Defines verdicts (NF_ACCEPT, etc) */
31 #include <libnetfilter_queue/libnetfilter_queue.h>
35 #include <arpa/inet.h> // ntohl
38 //-----------------------------------------------------------------------------
39 //-----------------------------------------------------------------------------
40 //-----------------------------------------------------------------------------
44 PLUGIN_CREATOR<NFQ_CAP> ncc;
46 int callback(struct nfq_q_handle * /*queueHandle*/, struct nfgenmsg * /*msg*/,
47 struct nfq_data * nfqData, void *data)
51 struct nfqnl_msg_packet_hdr * packetHeader = nfq_get_msg_packet_hdr(nfqData);
52 if (packetHeader == NULL)
55 id = ntohl(packetHeader->packet_id);
57 unsigned char * payload = NULL;
59 if (nfq_get_payload(nfqData) < 0)
64 memcpy(&packet.rawPacket, payload, sizeof(ip.rawPacket));
66 NFQ_CAP * cap = static_cast<NFQ_CAP *>(data);
70 return nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL);
75 extern "C" PLUGIN * GetPlugin();
76 //-----------------------------------------------------------------------------
77 //-----------------------------------------------------------------------------
78 //-----------------------------------------------------------------------------
81 return ncc.GetPlugin();
83 //-----------------------------------------------------------------------------
84 //-----------------------------------------------------------------------------
85 //-----------------------------------------------------------------------------
86 std::string NFQ_CAP::GetVersion() const
88 return "cap_nfqueue v.1.0";
90 //-----------------------------------------------------------------------------
97 logger(GetPluginLogger(GetStgLogger(), "cap_nfqueue"))
100 //-----------------------------------------------------------------------------
101 int NFQ_CAP::ParseSettings()
105 //-----------------------------------------------------------------------------
111 nfqHandle = nfq_open();
112 if (nfqHandle == NULL)
114 errorStr = "Failed to initialize netfilter queue.";
119 if (nfq_unbind_pf(nfqHandle, AF_INET) < 0)
121 errorStr = "Failed to unbind netfilter queue from IP handling.";
126 if (nfq_bind_pf(nfqHandle, AF_INET) < 0)
128 errorStr = "Failed to bind netfilter queue to IP handling.";
133 queueHandle = nfq_create_queue(nfqHandle, queueNumber, &Callback, this);
134 if (queueHandle == NULL)
136 errorStr = "Failed to create queue " + x2str(queueNumber) + ".";
141 if (nfq_set_mode(queueHandle, NFQNL_COPY_PACKET, 0xffFF) < 0)
143 errorStr = "Failed to set queue " + x2str(queueNumber) + " mode.";
150 if (pthread_create(&thread, NULL, Run, this))
152 errorStr = "Cannot create thread.";
153 logger("Cannot create thread.");
154 printfd(__FILE__, "Cannot create thread\n");
160 //-----------------------------------------------------------------------------
168 //5 seconds to thread stops itself
169 for (int i = 0; i < 25 && isRunning; i++)
171 struct timespec ts = {0, 200000000};
172 nanosleep(&ts, NULL);
174 //after 5 seconds waiting thread still running. now killing it
177 if (pthread_kill(thread, SIGUSR1))
179 errorStr = "Cannot kill thread.";
180 logger("Cannot send signal to thread.");
183 for (int i = 0; i < 25 && isRunning; ++i)
185 struct timespec ts = {0, 200000000};
186 nanosleep(&ts, NULL);
190 errorStr = "NFQ_CAP not stopped.";
191 logger("Cannot stop thread.");
192 printfd(__FILE__, "Cannot stop thread\n");
197 pthread_join(thread, NULL);
199 nfq_destroy_queue(queueHandle);
200 nfq_close(nfqHandle);
204 //-----------------------------------------------------------------------------
205 void * NFQ_CAP::Run(void * d)
208 sigfillset(&signalSet);
209 pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
211 NFQ_CAP * dc = static_cast<NFQ_CAP *>(d);
212 dc->isRunning = true;
214 int fd = nfq_fd(nfqHandle);
219 if (!WaitPackets(fd))
222 int rv = read(fd, buf, sizeof(buf), 0);
225 errorStr = "Read error: " + strerror(errno);
229 nfq_handle_packet(nfqHandle, buf, rv);
232 dc->isRunning = false;