]> git.stg.codes - stg.git/blob - projects/stargazer/plugins/capture/ipq_linux/ipq_cap.cpp
Merge branch 'master' into full-month-stats
[stg.git] / projects / stargazer / plugins / capture / ipq_linux / ipq_cap.cpp
1 /*
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.
6  *
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.
11  *
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
15  */
16
17 /*
18 * Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
19 */
20
21 #include <netinet/in.h>
22 #include <linux/netfilter.h>
23
24 #include <csignal>
25 #include <cerrno>
26 #include <cstring>
27
28 #include "stg/raw_ip_packet.h"
29 #include "stg/traffcounter.h"
30 #include "stg/plugin_creator.h"
31 #include "stg/common.h"
32
33 #include "ipq_cap.h"
34
35 extern "C"
36 {
37 #include "libipq.h"
38 }
39
40 //-----------------------------------------------------------------------------
41 //-----------------------------------------------------------------------------
42 //-----------------------------------------------------------------------------
43 PLUGIN_CREATOR<IPQ_CAP> icc;
44 //-----------------------------------------------------------------------------
45 //-----------------------------------------------------------------------------
46 //-----------------------------------------------------------------------------
47 PLUGIN * GetPlugin()
48 {
49 return icc.GetPlugin();
50 }
51 //-----------------------------------------------------------------------------
52 //-----------------------------------------------------------------------------
53 //-----------------------------------------------------------------------------
54 const std::string IPQ_CAP::GetVersion() const
55 {
56 return "ipq_cap v.1.2";
57 }
58 //-----------------------------------------------------------------------------
59 IPQ_CAP::IPQ_CAP()
60     : ipq_h(NULL),
61       errorStr(),
62       thread(),
63       nonstop(false),
64       isRunning(false),
65       capSock(-1),
66       traffCnt(NULL),
67       buf(),
68       logger(GetPluginLogger(GetStgLogger(), "cap_ipq"))
69 {
70 memset(buf, 0, BUFSIZE);
71 }
72 //-----------------------------------------------------------------------------
73 int IPQ_CAP::Start()
74 {
75 if (isRunning)
76     return 0;
77 if (IPQCapOpen() < 0)
78     {
79     errorStr = "Cannot open socket!";
80     printfd(__FILE__, "Cannot open socket\n");
81     return -1;
82     }
83 nonstop = true;
84 if (pthread_create(&thread, NULL, Run, this) == 0)
85     {
86     return 0;
87     }
88 errorStr = "Cannot create thread.";
89 printfd(__FILE__, "Cannot create thread\n");
90 return -1;
91 }
92 //-----------------------------------------------------------------------------
93 int IPQ_CAP::Stop()
94 {
95 if (!isRunning)
96     return 0;
97 nonstop = false;
98 //5 seconds to thread stops itself
99 for (int i = 0; i < 25; i++)
100     {
101     if (!isRunning)
102         break;
103     struct timespec ts = {0, 200000000};
104     nanosleep(&ts, NULL);
105     }
106 //after 5 seconds waiting thread still running. now killing it
107 if (isRunning)
108     {
109     if (pthread_kill(thread, SIGINT))
110         {
111         errorStr = "Cannot kill thread.";
112         return -1;
113         }
114     for (int i = 0; i < 25 && isRunning; ++i)
115         {
116         struct timespec ts = {0, 200000000};
117         nanosleep(&ts, NULL);
118         }
119     if (isRunning)
120         {
121         printfd(__FILE__, "Thread not stopped\n");
122         }
123     else
124         {
125         pthread_join(thread, NULL);
126         }
127     }
128 IPQCapClose();
129 return 0;
130 }
131 //-----------------------------------------------------------------------------
132 void * IPQ_CAP::Run(void * d)
133 {
134 sigset_t signalSet;
135 sigfillset(&signalSet);
136 pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
137
138 RAW_PACKET raw_packet;
139
140 IPQ_CAP * dc = static_cast<IPQ_CAP *>(d);
141 dc->isRunning = true;
142 memset(&raw_packet, 0, sizeof(raw_packet));
143 raw_packet.dataLen = -1;
144 while (dc->nonstop)
145     {
146     int status = dc->IPQCapRead(&raw_packet, 68);
147     if (status == -1 ||
148         status == -2 ||
149         status == -3 ||
150         status == -4)
151         continue;
152     dc->traffCnt->Process(raw_packet);
153     }
154 dc->isRunning = false;
155 return NULL;
156 }
157 //-----------------------------------------------------------------------------
158 int IPQ_CAP::IPQCapOpen()
159 {
160 ipq_h = ipq_create_handle(0, PF_INET);
161 if (ipq_h == NULL)
162     {
163     ipq_destroy_handle(ipq_h);
164     logger("Cannot create IPQ handle. Error: '%s', '%s'", ipq_errstr(), strerror(errno));
165     errorStr = "Cannot create ipq handle!";
166     return -1;
167     }
168 int status = ipq_set_mode(ipq_h, IPQ_COPY_PACKET, PAYLOAD_LEN);
169 if (status < 0)
170     {
171     ipq_destroy_handle(ipq_h);
172     logger("Cannot set IPQ_COPY_PACKET mode.");
173     errorStr = "Cannot set IPQ_COPY_PACKET mode!";
174     return -1;
175     }
176 return 0;
177 }
178 //-----------------------------------------------------------------------------
179 int IPQ_CAP::IPQCapClose()
180 {
181 ipq_destroy_handle(ipq_h);
182 return 0;
183 }
184 //-----------------------------------------------------------------------------
185 int IPQ_CAP::IPQCapRead(void * buffer, int blen)
186 {
187 memset(buf, 0, BUFSIZE);
188 int status = ipq_read(ipq_h, buf, BUFSIZE, 1);
189 if (status == 0)
190     return -4;
191 if (errno == EINTR)
192     return -3;
193 if (status < 0)
194     return -1;
195 if (ipq_message_type(buf) != IPQM_PACKET)
196     return -2;
197 static ipq_packet_msg_t * m = ipq_get_packet(buf);
198 memcpy(buffer, m->payload, blen);
199 ipq_set_verdict(ipq_h, m->packet_id, NF_ACCEPT, 0, NULL);
200 return 0;
201 }
202 //-----------------------------------------------------------------------------