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
22 * Author : Maxim Mamontov <faust@stg.dp.ua>
27 $Date: 2010/09/10 06:41:06 $
30 #include <sys/types.h>
31 #include <sys/socket.h>
32 #include <netinet/in.h>
33 #include <arpa/inet.h>
42 #include "stg/common.h"
43 #include "stg/raw_ip_packet.h"
44 #include "stg/traffcounter.h"
47 class CAP_NF_CREATOR {
59 NF_CAP * GetCapturer() { return nf; }
66 return cnc.GetCapturer();
88 int NF_CAP::ParseSettings()
90 std::vector<PARAM_VALUE>::iterator it;
91 for (it = settings.moduleParams.begin(); it != settings.moduleParams.end(); ++it)
93 if (it->param == "TCPPort")
95 if (str2x(it->value[0], portT))
97 errorStr = "Invalid TCPPort value";
98 printfd(__FILE__, "Error: Invalid TCPPort value\n");
103 if (it->param == "UDPPort")
105 if (str2x(it->value[0], portU))
107 errorStr = "Invalid UDPPort value";
108 printfd(__FILE__, "Error: Invalid UDPPort value\n");
113 printfd(__FILE__, "'%s' is not a valid module param\n", it->param.c_str());
127 if (pthread_create(&tidUDP, NULL, RunUDP, this))
131 errorStr = "Cannot create UDP thread";
132 printfd(__FILE__, "Error: Cannot create UDP thread\n");
143 if (pthread_create(&tidTCP, NULL, RunTCP, this))
147 errorStr = "Cannot create TCP thread";
148 printfd(__FILE__, "Error: Cannot create TCP thread\n");
157 runningTCP = runningUDP = false;
158 if (portU && !stoppedUDP)
161 for (int i = 0; i < 25 && !stoppedUDP; ++i)
167 pthread_join(tidUDP, NULL);
171 if (pthread_kill(tidUDP, SIGUSR1))
173 errorStr = "Error sending signal to UDP thread";
174 printfd(__FILE__, "Error: Error sending signal to UDP thread\n");
177 printfd(__FILE__, "UDP thread NOT stopped\n");
180 if (portT && !stoppedTCP)
183 for (int i = 0; i < 25 && !stoppedTCP; ++i)
189 pthread_join(tidTCP, NULL);
193 if (pthread_kill(tidTCP, SIGUSR1))
195 errorStr = "Error sending signal to TCP thread";
196 printfd(__FILE__, "Error: Error sending signal to TCP thread\n");
199 printfd(__FILE__, "TCP thread NOT stopped\n");
205 bool NF_CAP::OpenUDP()
207 struct sockaddr_in sin;
208 sockUDP = socket(PF_INET, SOCK_DGRAM, 0);
211 errorStr = "Error opening UDP socket";
212 printfd(__FILE__, "Error: Error opening UDP socket\n");
215 sin.sin_family = AF_INET;
216 sin.sin_port = htons(portU);
217 sin.sin_addr.s_addr = inet_addr("0.0.0.0");
218 if (bind(sockUDP, (struct sockaddr *)&sin, sizeof(sin)))
220 errorStr = "Error binding UDP socket";
221 printfd(__FILE__, "Error: Error binding UDP socket\n");
227 bool NF_CAP::OpenTCP()
229 struct sockaddr_in sin;
230 sockTCP = socket(PF_INET, SOCK_STREAM, 0);
233 errorStr = "Error opening TCP socket";
234 printfd(__FILE__, "Error: Error opening TCP socket\n");
237 sin.sin_family = AF_INET;
238 sin.sin_port = htons(portT);
239 sin.sin_addr.s_addr = inet_addr("0.0.0.0");
240 if (bind(sockTCP, (struct sockaddr *)&sin, sizeof(sin)))
242 errorStr = "Error binding TCP socket";
243 printfd(__FILE__, "Error: Error binding TCP socket\n");
246 if (listen(sockTCP, 1))
248 errorStr = "Error listening on TCP socket";
249 printfd(__FILE__, "Error: Error listening TCP socket\n");
255 void * NF_CAP::RunUDP(void * c)
257 NF_CAP * cap = static_cast<NF_CAP *>(c);
258 uint8_t buf[BUF_SIZE];
260 struct sockaddr_in sin;
262 cap->stoppedUDP = false;
263 while (cap->runningUDP)
265 if (!cap->WaitPackets(cap->sockUDP))
272 res = recvfrom(cap->sockUDP, buf, BUF_SIZE, 0, reinterpret_cast<struct sockaddr *>(&sin), &slen);
273 if (!cap->runningUDP)
285 cap->errorStr = "Invalid data received";
286 printfd(__FILE__, "Error: Invalid data received through UDP\n");
291 cap->ParseBuffer(buf, res);
293 cap->stoppedUDP = true;
297 void * NF_CAP::RunTCP(void * c)
299 NF_CAP * cap = static_cast<NF_CAP *>(c);
300 uint8_t buf[BUF_SIZE];
303 struct sockaddr_in sin;
305 cap->stoppedTCP = false;
306 while (cap->runningTCP)
308 if (!cap->WaitPackets(cap->sockTCP))
315 sd = accept(cap->sockTCP, reinterpret_cast<struct sockaddr *>(&sin), &slen);
316 if (!cap->runningTCP)
323 cap->errorStr = "Error accepting connection";
324 printfd(__FILE__, "Error: Error accepting connection\n");
329 if (!cap->WaitPackets(sd))
335 res = recv(sd, buf, BUF_SIZE, MSG_WAITALL);
338 if (!cap->runningTCP)
347 // Need to check actual data length and wait all data to receive
352 cap->errorStr = "Invalid data received";
353 printfd(__FILE__, "Error: Invalid data received through TCP\n");
358 cap->ParseBuffer(buf, res);
360 cap->stoppedTCP = true;
364 void NF_CAP::ParseBuffer(uint8_t * buf, int size)
367 NF_HEADER * hdr = reinterpret_cast<NF_HEADER *>(buf);
368 if (htons(hdr->version) != 5)
373 int packets = htons(hdr->count);
375 if (packets < 0 || packets > 30)
380 if (24 + 48 * packets != size)
382 // See 'wrong logic' upper
386 for (int i = 0; i < packets; ++i)
388 NF_DATA * data = reinterpret_cast<NF_DATA *>(buf + 24 + i * 48);
390 ip.header.ipHeader.ip_v = 4;
391 ip.header.ipHeader.ip_hl = 5;
392 ip.header.ipHeader.ip_p = data->proto;
393 ip.dataLen = ntohl(data->octets);
394 ip.header.ipHeader.ip_src.s_addr = data->srcAddr;
395 ip.header.ipHeader.ip_dst.s_addr = data->dstAddr;
396 ip.header.sPort = data->srcPort;
397 ip.header.dPort = data->dstPort;
399 traffCnt->Process(ip);
403 bool NF_CAP::WaitPackets(int sd) const
413 int res = select(sd + 1, &rfds, NULL, NULL, &tv);
414 if (res == -1) // Error
418 printfd(__FILE__, "Error on select: '%s'\n", strerror(errno));
423 if (res == 0) // Timeout