]> git.stg.codes - stg.git/blob - projects/stargazer/plugins/capture/cap_nf/cap_nf.cpp
Hide or add proper copy ctor and assignement operator, initialize
[stg.git] / projects / stargazer / plugins / capture / cap_nf / cap_nf.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 Date: 16.05.2008
19 */
20
21 /*
22 * Author : Maxim Mamontov <faust@stg.dp.ua>
23 */
24
25 /*
26 $Revision: 1.11 $
27 $Date: 2010/09/10 06:41:06 $
28 $Author: faust $
29 */
30 #include <sys/types.h>
31 #include <sys/socket.h>
32 #include <netinet/in.h>
33 #include <arpa/inet.h>
34 #include <unistd.h>
35
36 #include <csignal>
37 #include <cerrno>
38 #include <cstring>
39
40 #include <vector>
41
42 #include "stg/common.h" 
43 #include "stg/raw_ip_packet.h"
44 #include "stg/traffcounter.h"
45 #include "stg/plugin_creator.h"
46 #include "cap_nf.h"
47
48 PLUGIN_CREATOR<NF_CAP> cnc;
49
50 PLUGIN * GetPlugin()
51 {
52 return cnc.GetPlugin();
53 }
54
55 NF_CAP::NF_CAP()
56     : traffCnt(NULL),
57       settings(),
58       tidTCP(),
59       tidUDP(),
60       runningTCP(false),
61       runningUDP(false),
62       stoppedTCP(true),
63       stoppedUDP(true),
64       portT(0),
65       portU(0),
66       sockTCP(-1),
67       sockUDP(-1),
68       errorStr()
69 {
70 }
71
72 NF_CAP::~NF_CAP()
73 {
74 }
75
76 int NF_CAP::ParseSettings()
77 {
78 std::vector<PARAM_VALUE>::iterator it;
79 for (it = settings.moduleParams.begin(); it != settings.moduleParams.end(); ++it)
80     {
81     if (it->param == "TCPPort")
82         {
83         if (str2x(it->value[0], portT))
84             {
85             errorStr = "Invalid TCPPort value";
86             printfd(__FILE__, "Error: Invalid TCPPort value\n");
87             return -1;
88             }
89         continue;
90         }
91     if (it->param == "UDPPort")
92         {
93         if (str2x(it->value[0], portU))
94             {
95             errorStr = "Invalid UDPPort value";
96             printfd(__FILE__, "Error: Invalid UDPPort value\n");
97             return -1;
98             }
99         continue;
100         }
101     printfd(__FILE__, "'%s' is not a valid module param\n", it->param.c_str());
102     }
103 return 0;
104 }
105
106 int NF_CAP::Start()
107 {
108 if (portU > 0)
109     {
110     if (OpenUDP())
111         {
112         return -1;
113         }
114     runningUDP = true;
115     if (pthread_create(&tidUDP, NULL, RunUDP, this))
116         {
117         runningUDP = false;
118         CloseUDP();
119         errorStr = "Cannot create UDP thread";
120         printfd(__FILE__, "Error: Cannot create UDP thread\n");
121         return -1;
122         }
123     }
124 if (portT > 0)
125     {
126     if (OpenTCP())
127         {
128         return -1;
129         }
130     runningTCP = true;
131     if (pthread_create(&tidTCP, NULL, RunTCP, this))
132         {
133         runningTCP = false;
134         CloseTCP();
135         errorStr = "Cannot create TCP thread";
136         printfd(__FILE__, "Error: Cannot create TCP thread\n");
137         return -1;
138         }
139     }
140 return 0;
141 }
142
143 int NF_CAP::Stop()
144 {
145 runningTCP = runningUDP = false;
146 if (portU && !stoppedUDP)
147     {
148     CloseUDP();
149     for (int i = 0; i < 25 && !stoppedUDP; ++i)
150         {
151         usleep(200000);
152         }
153     if (stoppedUDP)
154         {
155         pthread_join(tidUDP, NULL);
156         }
157     else
158         {
159         if (pthread_kill(tidUDP, SIGUSR1))
160             {
161             errorStr = "Error sending signal to UDP thread";
162             printfd(__FILE__, "Error: Error sending signal to UDP thread\n");
163             return -1;
164             }
165         printfd(__FILE__, "UDP thread NOT stopped\n");
166         }
167     }
168 if (portT && !stoppedTCP)
169     {
170     CloseTCP();
171     for (int i = 0; i < 25 && !stoppedTCP; ++i)
172         {
173         usleep(200000);
174         }
175     if (stoppedTCP)
176         {
177         pthread_join(tidTCP, NULL);
178         }
179     else
180         {
181         if (pthread_kill(tidTCP, SIGUSR1))
182             {
183             errorStr = "Error sending signal to TCP thread";
184             printfd(__FILE__, "Error: Error sending signal to TCP thread\n");
185             return -1;
186             }
187         printfd(__FILE__, "TCP thread NOT stopped\n");
188         }
189     }
190 return 0;
191 }
192
193 bool NF_CAP::OpenUDP()
194 {
195 struct sockaddr_in sin;
196 sockUDP = socket(PF_INET, SOCK_DGRAM, 0);
197 if (sockUDP <= 0)
198     {
199     errorStr = "Error opening UDP socket";
200     printfd(__FILE__, "Error: Error opening UDP socket\n");
201     return true;
202     }
203 sin.sin_family = AF_INET;
204 sin.sin_port = htons(portU);
205 sin.sin_addr.s_addr = inet_addr("0.0.0.0");
206 if (bind(sockUDP, (struct sockaddr *)&sin, sizeof(sin)))
207     {
208     errorStr = "Error binding UDP socket";
209     printfd(__FILE__, "Error: Error binding UDP socket\n");
210     return true;
211     }
212 return false;
213 }
214
215 bool NF_CAP::OpenTCP()
216 {
217 struct sockaddr_in sin;
218 sockTCP = socket(PF_INET, SOCK_STREAM, 0);
219 if (sockTCP <= 0)
220     {
221     errorStr = "Error opening TCP socket";
222     printfd(__FILE__, "Error: Error opening TCP socket\n");
223     return true;
224     }
225 sin.sin_family = AF_INET;
226 sin.sin_port = htons(portT);
227 sin.sin_addr.s_addr = inet_addr("0.0.0.0");
228 if (bind(sockTCP, (struct sockaddr *)&sin, sizeof(sin)))
229     {
230     errorStr = "Error binding TCP socket";
231     printfd(__FILE__, "Error: Error binding TCP socket\n");
232     return true;
233     }
234 if (listen(sockTCP, 1))
235     {
236     errorStr = "Error listening on TCP socket";
237     printfd(__FILE__, "Error: Error listening TCP socket\n");
238     return true;
239     }
240 return false;
241 }
242
243 void * NF_CAP::RunUDP(void * c)
244 {
245 NF_CAP * cap = static_cast<NF_CAP *>(c);
246 uint8_t buf[BUF_SIZE];
247 int res;
248 struct sockaddr_in sin;
249 socklen_t slen;
250 cap->stoppedUDP = false;
251 while (cap->runningUDP)
252     {
253     if (!WaitPackets(cap->sockUDP))
254         {
255         continue;
256         }
257
258     // Data
259     slen = sizeof(sin);
260     res = recvfrom(cap->sockUDP, buf, BUF_SIZE, 0, reinterpret_cast<struct sockaddr *>(&sin), &slen);
261     if (!cap->runningUDP)
262         break;
263
264     if (res == 0) // EOF
265         {
266         continue;
267         }
268
269     if (res < 24)
270         {
271         if (errno != EINTR)
272             {
273             cap->errorStr = "Invalid data received";
274             printfd(__FILE__, "Error: Invalid data received through UDP\n");
275             }
276         continue;
277         }
278
279     cap->ParseBuffer(buf, res);
280     }
281 cap->stoppedUDP = true;
282 return NULL;
283 }
284
285 void * NF_CAP::RunTCP(void * c)
286 {
287 NF_CAP * cap = static_cast<NF_CAP *>(c);
288 uint8_t buf[BUF_SIZE];
289 int res;
290 int sd;
291 struct sockaddr_in sin;
292 socklen_t slen;
293 cap->stoppedTCP = false;
294 while (cap->runningTCP)
295     {
296     if (!WaitPackets(cap->sockTCP))
297         {
298         continue;
299         }
300
301     // Data
302     slen = sizeof(sin);
303     sd = accept(cap->sockTCP, reinterpret_cast<struct sockaddr *>(&sin), &slen);
304     if (!cap->runningTCP)
305         break;
306
307     if (sd <= 0)
308         {
309         if (errno != EINTR)
310             {
311             cap->errorStr = "Error accepting connection";
312             printfd(__FILE__, "Error: Error accepting connection\n");
313             }
314         continue;
315         }
316
317     if (!WaitPackets(sd))
318         {
319         close(sd);
320         continue;
321         }
322
323     res = recv(sd, buf, BUF_SIZE, MSG_WAITALL);
324     close(sd);
325
326     if (!cap->runningTCP)
327         break;
328
329     if (res == 0) // EOF
330         {
331         continue;
332         }
333
334     // Wrong logic!
335     // Need to check actual data length and wait all data to receive
336     if (res < 24)
337         {
338         if (errno != EINTR)
339             {
340             cap->errorStr = "Invalid data received";
341             printfd(__FILE__, "Error: Invalid data received through TCP\n");
342             }
343         continue;
344         }
345
346     cap->ParseBuffer(buf, res);
347     }
348 cap->stoppedTCP = true;
349 return NULL;
350 }
351
352 void NF_CAP::ParseBuffer(uint8_t * buf, int size)
353 {
354 RAW_PACKET ip;
355 NF_HEADER * hdr = reinterpret_cast<NF_HEADER *>(buf);
356 if (htons(hdr->version) != 5)
357     {
358     return;
359     }
360
361 int packets = htons(hdr->count);
362
363 if (packets < 0 || packets > 30)
364     {
365     return;
366     }
367
368 if (24 + 48 * packets != size)
369     {
370     // See 'wrong logic' upper
371     return;
372     }
373
374 for (int i = 0; i < packets; ++i)
375     {
376     NF_DATA * data = reinterpret_cast<NF_DATA *>(buf + 24 + i * 48);
377
378     ip.rawPacket.header.ipHeader.ip_v = 4;
379     ip.rawPacket.header.ipHeader.ip_hl = 5;
380     ip.rawPacket.header.ipHeader.ip_p = data->proto;
381     ip.dataLen = ntohl(data->octets);
382     ip.rawPacket.header.ipHeader.ip_src.s_addr = data->srcAddr;
383     ip.rawPacket.header.ipHeader.ip_dst.s_addr = data->dstAddr;
384     ip.rawPacket.header.sPort = data->srcPort;
385     ip.rawPacket.header.dPort = data->dstPort;
386
387     traffCnt->Process(ip);
388     }
389 }