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