]> git.stg.codes - stg.git/blob - projects/stargazer/plugins/capture/divert_freebsd/divert_cap.cpp
Fix TRAFFCOUNTER in plugins
[stg.git] / projects / stargazer / plugins / capture / divert_freebsd / divert_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@stg.dp.ua>
19 */
20
21 /*
22 $Revision: 1.13 $
23 $Date: 2010/09/10 06:43:03 $
24 */
25 #include <stdio.h>
26 #include <sys/types.h>
27 #include <sys/socket.h>
28 #include <netinet/in.h>
29 #include <string.h>
30
31 #include <sys/uio.h>
32 #include <sys/time.h>
33 #include <sys/ioctl.h>
34 #include <sys/poll.h>
35
36 #include <errno.h>
37 #include <fcntl.h>
38 #include <stdlib.h>
39 #include <signal.h>
40 #include <unistd.h>
41
42 #include "common.h"
43 #include "divert_cap.h"
44 #include "traffcounter.h"
45
46 #define BUFF_LEN (16384) /* max mtu -> lo=16436  TODO why?*/
47
48 //-----------------------------------------------------------------------------
49 struct DIVERT_DATA {
50 int sock;
51 short int port;
52 unsigned char buffer[BUFF_LEN];
53 char iface[10];
54 };
55 //-----------------------------------------------------------------------------
56 pollfd pollddiv;
57 DIVERT_DATA cddiv;  //capture data
58 //-----------------------------------------------------------------------------
59 class DIVERT_CAP_CREATOR {
60 private:
61     DIVERT_CAP * divc;
62
63 public:
64     DIVERT_CAP_CREATOR()
65         : divc(new DIVERT_CAP())
66         {
67         }
68     ~DIVERT_CAP_CREATOR()
69         {
70         delete divc;
71         }
72
73     DIVERT_CAP * GetCapturer()
74     {
75     return divc;
76     }
77 };
78 //-----------------------------------------------------------------------------
79 //-----------------------------------------------------------------------------
80 //-----------------------------------------------------------------------------
81 DIVERT_CAP_CREATOR dcc;
82 //-----------------------------------------------------------------------------
83 //-----------------------------------------------------------------------------
84 //-----------------------------------------------------------------------------
85 PLUGIN * GetPlugin()
86 {
87 return dcc.GetCapturer();
88 }
89 //-----------------------------------------------------------------------------
90 //-----------------------------------------------------------------------------
91 //-----------------------------------------------------------------------------
92 const std::string DIVERT_CAP::GetVersion() const
93 {
94 return "Divert_cap v.1.0";
95 }
96 //-----------------------------------------------------------------------------
97 DIVERT_CAP::DIVERT_CAP()
98     : port(0),
99       nonstop(false),
100       isRunning(false),
101       traffCnt(NULL)
102 {
103 }
104 //-----------------------------------------------------------------------------
105 int DIVERT_CAP::Start()
106 {
107 if (isRunning)
108     return 0;
109
110 if (DivertCapOpen() < 0)
111     {
112     errorStr = "Cannot open socket!";
113     printfd(__FILE__, "Cannot open socket\n");
114     return -1;
115     }
116
117 nonstop = true;
118
119 if (pthread_create(&thread, NULL, Run, this) == 0)
120     {
121     return 0;
122     }
123
124 errorStr = "Cannot create thread.";
125 printfd(__FILE__, "Cannot create thread\n");
126 return -1;
127 }
128 //-----------------------------------------------------------------------------
129 int DIVERT_CAP::Stop()
130 {
131 if (!isRunning)
132     return 0;
133
134 DivertCapClose();
135
136 nonstop = false;
137
138 //5 seconds to thread stops itself
139 int i;
140 for (i = 0; i < 25; i++)
141     {
142     if (!isRunning)
143         break;
144
145     usleep(200000);
146     }
147
148 //after 5 seconds waiting thread still running. now killing it
149 if (isRunning)
150     {
151     if (pthread_kill(thread, SIGINT))
152         {
153         errorStr = "Cannot kill thread.";
154         printfd(__FILE__, "Cannot kill thread\n");
155         return -1;
156         }
157     }
158
159 return 0;
160 }
161 //-----------------------------------------------------------------------------
162 void * DIVERT_CAP::Run(void * d)
163 {
164 DIVERT_CAP * dc = (DIVERT_CAP *)d;
165 dc->isRunning = true;
166
167 char buffer[64];
168 while (dc->nonstop)
169     {
170     RAW_PACKET rp;
171     dc->DivertCapRead(buffer, 64, NULL);
172
173     if (buffer[12] != 0x8)
174         continue;
175
176     memcpy(rp.pckt, &buffer[14], pcktSize);
177
178     dc->traffCnt->Process(rp);
179     }
180
181 dc->isRunning = false;
182 return NULL;
183 }
184 //-----------------------------------------------------------------------------
185 int DIVERT_CAP::DivertCapOpen()
186 {
187 memset(&pollddiv, 0, sizeof(pollddiv));
188 memset(&cddiv, 0, sizeof(DIVERT_DATA));
189
190 strcpy(cddiv.iface, "foo");
191 cddiv.port = port;
192
193 DivertCapOpen(0);
194 pollddiv.events = POLLIN;
195 pollddiv.fd = cddiv.sock;
196
197 return 0;
198 }
199 //-----------------------------------------------------------------------------
200 int DIVERT_CAP::DivertCapOpen(int)
201 {
202 int ret;
203 cddiv.sock = socket(PF_INET, SOCK_RAW, IPPROTO_DIVERT);
204 if (cddiv.sock < 0)
205     {
206     errorStr = "Create divert socket error.";
207     printfd(__FILE__, "Cannot create divert socket\n");
208     return -1;
209     }
210
211 struct sockaddr_in divAddr;
212
213 memset(&divAddr, 0, sizeof(divAddr));
214
215 divAddr.sin_family = AF_INET;
216 divAddr.sin_port = htons(cddiv.port);
217 divAddr.sin_addr.s_addr = INADDR_ANY;
218
219 ret = bind(cddiv.sock, (struct sockaddr *)&divAddr, sizeof(divAddr));
220
221 if (ret < 0)
222     {
223     errorStr = "Bind divert socket error.";
224     printfd(__FILE__, "Cannot bind divert socket\n");
225     return -1;
226     }
227
228 return cddiv.sock;
229 }
230 //-----------------------------------------------------------------------------
231 int DIVERT_CAP::DivertCapRead(char * b, int blen, char ** iface)
232 {
233 poll(&pollddiv, 1, -1);
234
235 if (pollddiv.revents & POLLIN)
236     {
237     DivertCapRead(b, blen, iface, 0);
238     pollddiv.revents = 0;
239     return 0;
240     }
241
242 return 0;
243 }
244 //-----------------------------------------------------------------------------
245 int DIVERT_CAP::DivertCapRead(char * b, int blen, char ** iface, int)
246 {
247 static char buf[BUFF_LEN];
248 static struct sockaddr_in divertaddr;
249 static int bytes;
250 static socklen_t divertaddrSize = sizeof(divertaddr);
251
252 if ((bytes = recvfrom (cddiv.sock, buf, BUFF_LEN,
253                        0, (struct sockaddr*) &divertaddr, &divertaddrSize)) > 50)
254     {
255     memcpy(b + 14, buf, blen - 14);
256     b[12] = 0x8;
257
258     if (iface)
259         *iface = cddiv.iface;
260
261     sendto(cddiv.sock, buf, bytes, 0, (struct sockaddr*)&divertaddr, divertaddrSize);
262     }
263
264 return 0;
265 }
266 //-----------------------------------------------------------------------------
267 int DIVERT_CAP::DivertCapClose()
268 {
269 close(cddiv.sock);
270 return 0;
271 }
272 //-----------------------------------------------------------------------------
273 int DIVERT_CAP::ParseSettings()
274 {
275 int p;
276 PARAM_VALUE pv;
277 vector<PARAM_VALUE>::const_iterator pvi;
278
279 pv.param = "Port";
280 pvi = find(settings.moduleParams.begin(), settings.moduleParams.end(), pv);
281 if (pvi == settings.moduleParams.end())
282     {
283     port = 15701;
284     return 0;
285     }
286
287 if (ParseIntInRange(pvi->value[0], 1, 65535, &p))
288     {
289     errorStr = "Cannot parse parameter \'Port\': " + errorStr;
290     printfd(__FILE__, "Cannot parse parameter 'Port'\n");
291     return -1;
292     }
293
294 port = p;
295
296 return 0;
297 }
298 //-----------------------------------------------------------------------------
299 int DIVERT_CAP::ParseIntInRange(const std::string & str, int min, int max, int * val)
300 {
301 if (str2x(str.c_str(), *val))
302     {
303     errorStr = "Incorrect value \'" + str + "\'.";
304     return -1;
305     }
306 if (*val < min || *val > max)
307     {
308     errorStr = "Value \'" + str + "\' out of range.";
309     return -1;
310     }
311 return 0;
312 }
313 //-----------------------------------------------------------------------------