]> git.stg.codes - stg.git/blob - projects/stargazer/traffcounter_impl.cpp
Full and correct rollback in SMUX::Stop method
[stg.git] / projects / stargazer / traffcounter_impl.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: 27.10.2002
19  */
20
21 /*
22  *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
23  */
24
25 /*
26  $Revision: 1.58 $
27  $Date: 2010/11/03 11:28:07 $
28  $Author: faust $
29  */
30
31 /* inet_aton */
32 #include <sys/types.h>
33 #include <sys/socket.h>
34 #include <netinet/in.h>
35 #include <arpa/inet.h>
36
37 #include <csignal>
38 #include <cassert>
39 #include <cstdio> // fopen and similar
40 #include <cstdlib> // strtol
41
42 #include "stg/common.h"
43 #include "stg/locker.h"
44 #include "traffcounter_impl.h"
45 #include "stg_timer.h"
46 #include "users_impl.h"
47
48 #define FLUSH_TIME  (10)
49 #define REMOVE_TIME  (31)
50
51 const char protoName[PROTOMAX][8] =
52 {"TCP", "UDP", "ICMP", "TCP_UDP", "ALL"};
53
54 enum protoNum
55 {
56 tcp = 0, udp, icmp, tcp_udp, all
57 };
58
59 //-----------------------------------------------------------------------------
60 TRAFFCOUNTER_IMPL::TRAFFCOUNTER_IMPL(USERS_IMPL * u, const std::string & fn)
61     : TRAFFCOUNTER(),
62       WriteServLog(GetStgLogger()),
63       rulesFileName(fn),
64       monitoring(false),
65       users(u),
66       running(false),
67       stopped(true),
68       addUserNotifier(*this),
69       delUserNotifier(*this)
70 {
71 for (int i = 0; i < DIR_NUM; i++)
72     strprintf(&dirName[i], "DIR%d", i);
73
74 dirName[DIR_NUM] = "NULL";
75
76 users->AddNotifierUserAdd(&addUserNotifier);
77 users->AddNotifierUserDel(&delUserNotifier);
78
79 pthread_mutex_init(&mutex, NULL);
80 }
81 //-----------------------------------------------------------------------------
82 TRAFFCOUNTER_IMPL::~TRAFFCOUNTER_IMPL()
83 {
84 pthread_mutex_destroy(&mutex);
85 }
86 //-----------------------------------------------------------------------------
87 int TRAFFCOUNTER_IMPL::Start()
88 {
89 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
90
91 if (!stopped)
92     return 0;
93
94 if (ReadRules())
95     {
96     printfd(__FILE__, "TRAFFCOUNTER_IMPL::Start() - Cannot read rules\n");
97     WriteServLog("TRAFFCOUNTER: Cannot read rules.");
98     return -1;
99     }
100
101 printfd(__FILE__, "TRAFFCOUNTER::Start()\n");
102 int h = users->OpenSearch();
103 assert(h && "USERS::OpenSearch is always correct");
104 USER_IMPL * u;
105
106 while (users->SearchNext(h, &u) == 0)
107     {
108     SetUserNotifiers(u);
109     }
110 users->CloseSearch(h);
111
112 running = true;
113 if (pthread_create(&thread, NULL, Run, this))
114     {
115     printfd(__FILE__, "TRAFFCOUNTER_IMPL::Start() - Cannot start thread\n");
116     WriteServLog("TRAFFCOUNTER: Error: Cannot start thread.");
117     return -1;
118     }
119 return 0;
120 }
121 //-----------------------------------------------------------------------------
122 int TRAFFCOUNTER_IMPL::Stop()
123 {
124 if (stopped)
125     return 0;
126
127 running = false;
128
129 int h = users->OpenSearch();
130 assert(h && "USERS::OpenSearch is always correct");
131
132 USER_IMPL * u;
133 while (users->SearchNext(h, &u) == 0)
134     {
135     UnSetUserNotifiers(u);
136     }
137 users->CloseSearch(h);
138
139 //5 seconds to thread stops itself
140 struct timespec ts = {0, 200000000};
141 for (int i = 0; i < 25 && !stopped; i++)
142     {
143     nanosleep(&ts, NULL);
144     }
145
146 //after 5 seconds waiting thread still running. now kill it
147 if (!stopped)
148     {
149     printfd(__FILE__, "kill TRAFFCOUNTER thread.\n");
150     if (pthread_kill(thread, SIGINT))
151         {
152         return -1;
153         }
154     printfd(__FILE__, "TRAFFCOUNTER killed\n");
155     }
156 printfd(__FILE__, "TRAFFCOUNTER::Stop()\n");
157
158 return 0;
159 }
160 //-----------------------------------------------------------------------------
161 void * TRAFFCOUNTER_IMPL::Run(void * data)
162 {
163 TRAFFCOUNTER_IMPL * tc = static_cast<TRAFFCOUNTER_IMPL *>(data);
164 tc->stopped = false;
165 int c = 0;
166
167 time_t touchTime = stgTime - MONITOR_TIME_DELAY_SEC;
168 struct timespec ts = {0, 500000000};
169 while (tc->running)
170     {
171     nanosleep(&ts, 0);
172     if (!tc->running)
173         {
174         tc->FlushAndRemove();
175         break;
176         }
177
178     if (tc->monitoring && (touchTime + MONITOR_TIME_DELAY_SEC <= stgTime))
179         {
180         std::string monFile(tc->monitorDir + "/traffcounter_r");
181         printfd(__FILE__, "Monitor=%d file TRAFFCOUNTER %s\n", tc->monitoring, monFile.c_str());
182         touchTime = stgTime;
183         TouchFile(monFile.c_str());
184         }
185
186     if (++c % FLUSH_TIME == 0)
187         tc->FlushAndRemove();
188     }
189
190 tc->stopped = true;
191 return NULL;
192 }
193 //-----------------------------------------------------------------------------
194 void TRAFFCOUNTER_IMPL::Process(const RAW_PACKET & rawPacket)
195 {
196 if (!running)
197     return;
198
199 static time_t touchTime = stgTime - MONITOR_TIME_DELAY_SEC;
200
201 if (monitoring && (touchTime + MONITOR_TIME_DELAY_SEC <= stgTime))
202     {
203     static std::string monFile = monitorDir + "/traffcounter_p";
204     printfd(__FILE__, "Monitor=%d file TRAFFCOUNTER %s\n", monitoring, monFile.c_str());
205     touchTime = stgTime;
206     TouchFile(monFile.c_str());
207     }
208
209 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
210
211 //printfd(__FILE__, "TRAFFCOUNTER::Process()\n");
212 //TODO replace find with lower_bound.
213
214 // Searching a new packet in a tree.
215 pp_iter pi = packets.find(rawPacket);
216
217 // Packet found - update length and time
218 if (pi != packets.end())
219     {
220     pi->second.lenU += rawPacket.GetLen();
221     pi->second.lenD += rawPacket.GetLen();
222     pi->second.updateTime = stgTime;
223     /*printfd(__FILE__, "=============================\n");
224     printfd(__FILE__, "Packet found!\n");
225     printfd(__FILE__, "Version=%d\n", rawPacket.GetIPVersion());
226     printfd(__FILE__, "HeaderLen=%d\n", rawPacket.GetHeaderLen());
227     printfd(__FILE__, "PacketLen=%d\n", rawPacket.GetLen());
228     printfd(__FILE__, "SIP=%s\n", inet_ntostring(rawPacket.GetSrcIP()).c_str());
229     printfd(__FILE__, "DIP=%s\n", inet_ntostring(rawPacket.GetDstIP()).c_str());
230     printfd(__FILE__, "src port=%d\n", rawPacket.GetSrcPort());
231     printfd(__FILE__, "pst port=%d\n", rawPacket.GetDstPort());
232     printfd(__FILE__, "len=%d\n", rawPacket.GetLen());
233     printfd(__FILE__, "proto=%d\n", rawPacket.GetProto());
234     printfd(__FILE__, "PacketDirU=%d\n", pi->second.dirU);
235     printfd(__FILE__, "PacketDirD=%d\n", pi->second.dirD);
236     printfd(__FILE__, "=============================\n");*/
237     return;
238     }
239
240 PACKET_EXTRA_DATA ed;
241
242 // Packet not found - add new packet
243
244 ed.updateTime = stgTime;
245 ed.flushTime = stgTime;
246
247 /*
248  userU is that whose user_ip == packet_ip_src
249  userD is that whose user_ip == packet_ip_dst
250  */
251
252 uint32_t ipU = rawPacket.GetSrcIP();
253 uint32_t ipD = rawPacket.GetDstIP();
254
255 // Searching users with such IP
256 if (users->FindByIPIdx(ipU, &ed.userU) == 0)
257     {
258     ed.userUPresent = true;
259     }
260
261 if (users->FindByIPIdx(ipD, &ed.userD) == 0)
262     {
263     ed.userDPresent = true;
264     }
265
266 if (ed.userUPresent ||
267     ed.userDPresent)
268     {
269     DeterminateDir(rawPacket, &ed.dirU, &ed.dirD);
270
271     ed.lenD = ed.lenU = rawPacket.GetLen();
272
273     //TODO use result of lower_bound to inserting new record
274
275     // Adding packet to a tree.
276     std::pair<pp_iter, bool> insertResult = packets.insert(std::make_pair(rawPacket, ed));
277     pp_iter newPacket = insertResult.first;
278
279     // Adding packet reference to an IP index.
280     ip2packets.insert(std::make_pair(ipU, newPacket));
281     ip2packets.insert(std::make_pair(ipD, newPacket));
282     }
283 }
284 //-----------------------------------------------------------------------------
285 void TRAFFCOUNTER_IMPL::FlushAndRemove()
286 {
287 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
288
289 int oldPacketsSize = packets.size();
290 int oldIp2packetsSize = ip2packets.size();
291
292 pp_iter pi;
293 pi = packets.begin();
294 std::map<RAW_PACKET, PACKET_EXTRA_DATA> newPackets;
295 ip2packets.erase(ip2packets.begin(), ip2packets.end());
296 while (pi != packets.end())
297     {
298     //Flushing
299     if (stgTime - pi->second.flushTime > FLUSH_TIME)
300         {
301         if (pi->second.userUPresent)
302             {
303             //printfd(__FILE__, "+++ Flushing U user %s (%s:%d) of length %d\n", pi->second.userU->GetLogin().c_str(), inet_ntostring(pi->first.GetSrcIP()).c_str(), pi->first.GetSrcPort(), pi->second.lenU);
304
305             // Add stat
306             if (pi->second.dirU < DIR_NUM)
307                 {
308                 #ifdef TRAFF_STAT_WITH_PORTS
309                 pi->second.userU->AddTraffStatU(pi->second.dirU,
310                                                 pi->first.GetDstIP(),
311                                                 pi->first.GetDstPort(),
312                                                 pi->second.lenU);
313                 #else
314                 pi->second.userU->AddTraffStatU(pi->second.dirU,
315                                                 pi->first.GetDstIP(),
316                                                 pi->second.lenU);
317                 #endif
318                 }
319
320             pi->second.lenU = 0;
321             pi->second.flushTime = stgTime;
322             }
323
324         if (pi->second.userDPresent)
325             {
326             //printfd(__FILE__, "+++ Flushing D user %s (%s:%d) of length %d\n", pi->second.userD->GetLogin().c_str(), inet_ntostring(pi->first.GetDstIP()).c_str(), pi->first.GetDstPort(), pi->second.lenD);
327
328             // Add stat
329             if (pi->second.dirD < DIR_NUM)
330                 {
331                 #ifdef TRAFF_STAT_WITH_PORTS
332                 pi->second.userD->AddTraffStatD(pi->second.dirD,
333                                                 pi->first.GetSrcIP(),
334                                                 pi->first.GetSrcPort(),
335                                                 pi->second.lenD);
336                 #else
337                 pi->second.userD->AddTraffStatD(pi->second.dirD,
338                                                 pi->first.GetSrcIP(),
339                                                 pi->second.lenD);
340                 #endif
341                 }
342
343             pi->second.lenD = 0;
344             pi->second.flushTime = stgTime;
345             }
346         }
347
348     if (stgTime - pi->second.updateTime < REMOVE_TIME)
349         {
350         std::pair<pp_iter, bool> res = newPackets.insert(*pi);
351         if (res.second)
352             {
353             ip2packets.insert(std::make_pair(pi->first.GetSrcIP(), res.first));
354             ip2packets.insert(std::make_pair(pi->first.GetDstIP(), res.first));
355             }
356         }
357     ++pi;
358     }
359 swap(packets, newPackets);
360 printfd(__FILE__, "FlushAndRemove() packets: %d(rem %d) ip2packets: %d(rem %d)\n",
361         packets.size(),
362         oldPacketsSize - packets.size(),
363         ip2packets.size(),
364         oldIp2packetsSize - ip2packets.size());
365
366 }
367 //-----------------------------------------------------------------------------
368 void TRAFFCOUNTER_IMPL::AddUser(USER_IMPL * user)
369 {
370 printfd(__FILE__, "AddUser: %s\n", user->GetLogin().c_str());
371 uint32_t uip = user->GetCurrIP();
372 std::pair<ip2p_iter, ip2p_iter> pi;
373
374 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
375 // Find all packets with IP belongs to this user
376 pi = ip2packets.equal_range(uip);
377
378 while (pi.first != pi.second)
379     {
380     if (pi.first->second->first.GetSrcIP() == uip)
381         {
382         assert((!pi.first->second->second.userUPresent || 
383                  pi.first->second->second.userU == user) &&
384                "U user present but it's not current user");
385
386         pi.first->second->second.lenU = 0;
387         pi.first->second->second.userU = user;
388         pi.first->second->second.userUPresent = true;
389         }
390
391     if (pi.first->second->first.GetDstIP() == uip)
392         {
393         assert((!pi.first->second->second.userDPresent || 
394                  pi.first->second->second.userD == user) &&
395                "D user present but it's not current user");
396
397         pi.first->second->second.lenD = 0;
398         pi.first->second->second.userD = user;
399         pi.first->second->second.userDPresent = true;
400         }
401
402     ++pi.first;
403     }
404 }
405 //-----------------------------------------------------------------------------
406 void TRAFFCOUNTER_IMPL::DelUser(uint32_t uip)
407 {
408 printfd(__FILE__, "DelUser: %s \n", inet_ntostring(uip).c_str());
409 std::pair<ip2p_iter, ip2p_iter> pi;
410
411 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
412 pi = ip2packets.equal_range(uip);
413
414 while (pi.first != pi.second)
415     {
416     if (pi.first->second->first.GetSrcIP() == uip)
417         {
418         if (pi.first->second->second.dirU < DIR_NUM && pi.first->second->second.userUPresent)
419             {
420             #ifdef TRAFF_STAT_WITH_PORTS
421             pi.first->second->second.userU->AddTraffStatU(pi.first->second->second.dirU,
422                                                           pi.first->second->first.GetDstIP(),
423                                                           pi.first->second->first.GetDstPort(),
424                                                           pi.first->second->second.lenU);
425             #else
426             pi.first->second->second.userU->AddTraffStatU(pi.first->second->second.dirU,
427                                                           pi.first->second->first.GetDstIP(),
428                                                           pi.first->second->second.lenU);
429             #endif
430             }
431         pi.first->second->second.userUPresent = false;
432         }
433
434     if (pi.first->second->first.GetDstIP() == uip)
435         {
436         if (pi.first->second->second.dirD < DIR_NUM && pi.first->second->second.userDPresent)
437             {
438             #ifdef TRAFF_STAT_WITH_PORTS
439             pi.first->second->second.userD->AddTraffStatD(pi.first->second->second.dirD,
440                                                           pi.first->second->first.GetSrcIP(),
441                                                           pi.first->second->first.GetSrcPort(),
442                                                           pi.first->second->second.lenD);
443             #else
444             pi.first->second->second.userD->AddTraffStatD(pi.first->second->second.dirD,
445                                                           pi.first->second->first.GetSrcIP(),
446                                                           pi.first->second->second.lenD);
447             #endif
448             }
449
450         pi.first->second->second.userDPresent = false;
451         }
452
453     ++pi.first;
454     }
455
456 ip2packets.erase(pi.first, pi.second);
457 }
458 //-----------------------------------------------------------------------------
459 void TRAFFCOUNTER_IMPL::SetUserNotifiers(USER_IMPL * user)
460 {
461 // Adding user. Adding notifiers to user.
462 TRF_IP_BEFORE ipBNotifier(*this, user);
463 ipBeforeNotifiers.push_front(ipBNotifier);
464 user->AddCurrIPBeforeNotifier(&(*ipBeforeNotifiers.begin()));
465
466 TRF_IP_AFTER ipANotifier(*this, user);
467 ipAfterNotifiers.push_front(ipANotifier);
468 user->AddCurrIPAfterNotifier(&(*ipAfterNotifiers.begin()));
469 }
470 //-----------------------------------------------------------------------------
471 void TRAFFCOUNTER_IMPL::UnSetUserNotifiers(USER_IMPL * user)
472 {
473 // Removing user. Removing notifiers from user.
474 std::list<TRF_IP_BEFORE>::iterator bi;
475 std::list<TRF_IP_AFTER>::iterator ai;
476
477 bi = ipBeforeNotifiers.begin();
478 while (bi != ipBeforeNotifiers.end())
479     {
480     if (user->GetLogin() == bi->GetUser()->GetLogin())
481         {
482         user->DelCurrIPBeforeNotifier(&(*bi));
483         ipBeforeNotifiers.erase(bi);
484         break;
485         }
486     ++bi;
487     }
488
489 ai = ipAfterNotifiers.begin();
490 while (ai != ipAfterNotifiers.end())
491     {
492     if (user->GetLogin() == ai->GetUser()->GetLogin())
493         {
494         user->DelCurrIPAfterNotifier(&(*ai));
495         ipAfterNotifiers.erase(ai);
496         break;
497         }
498     ++ai;
499     }
500 }
501 //-----------------------------------------------------------------------------
502 void TRAFFCOUNTER_IMPL::DeterminateDir(const RAW_PACKET & packet,
503                                        int * dirU, // Direction for incoming packet
504                                        int * dirD) const // Direction for outgoing packet
505 {
506 bool addrMatchU;
507 bool portMatchU;
508 bool addrMatchD;
509 bool portMatchD;
510 bool foundU = false; // Was rule for U found ?
511 bool foundD = false; // Was rule for D found ?
512 //printfd(__FILE__, "foundU=%d, foundD=%d\n", foundU, foundD);
513
514 enum { ICMP_RPOTO = 1, TCP_PROTO = 6, UDP_PROTO = 17 };
515
516 std::list<RULE>::const_iterator ln;
517 ln = rules.begin();
518
519 while (ln != rules.end())
520     {
521     if (!foundU)
522         {
523         addrMatchU = false;
524         portMatchU = false;
525
526         switch (ln->proto)
527             {
528             case all:
529                 portMatchU = true;
530                 break;
531
532             case icmp:
533                 portMatchU = (packet.GetProto() == ICMP_RPOTO);
534                 break;
535
536             case tcp_udp:
537                 if (packet.GetProto() == TCP_PROTO || packet.GetProto() == UDP_PROTO)
538                     portMatchU = (packet.GetDstPort() >= ln->port1) && (packet.GetDstPort() <= ln->port2);
539                 break;
540
541             case tcp:
542                 if (packet.GetProto() == TCP_PROTO)
543                     portMatchU = (packet.GetDstPort() >= ln->port1) && (packet.GetDstPort() <= ln->port2);
544                 break;
545
546             case udp:
547                 if (packet.GetProto() == UDP_PROTO)
548                     portMatchU = (packet.GetDstPort() >= ln->port1) && (packet.GetDstPort() <= ln->port2);
549                 break;
550
551             default:
552                 printfd(__FILE__, "Error! Incorrect rule!\n");
553                 break;
554             }
555
556         addrMatchU = (packet.GetDstIP() & ln->mask) == ln->ip;
557
558         if (!foundU && addrMatchU && portMatchU)
559             {
560             foundU = true;
561             *dirU = ln->dir;
562             //printfd(__FILE__, "Up rule ok! %d\n", ln->dir);
563             //PrintRule(ln->rule);
564             }
565
566         } //if (!foundU)
567
568     if (!foundD)
569         {
570         addrMatchD = false;
571         portMatchD = false;
572
573         switch (ln->proto)
574             {
575             case all:
576                 portMatchD = true;
577                 break;
578
579             case icmp:
580                 portMatchD = (packet.GetProto() == ICMP_RPOTO);
581                 break;
582
583             case tcp_udp:
584                 if (packet.GetProto() == TCP_PROTO || packet.GetProto() == UDP_PROTO)
585                     portMatchD = (packet.GetSrcPort() >= ln->port1) && (packet.GetSrcPort() <= ln->port2);
586                 break;
587
588             case tcp:
589                 if (packet.GetProto() == TCP_PROTO)
590                     portMatchD = (packet.GetSrcPort() >= ln->port1) && (packet.GetSrcPort() <= ln->port2);
591                 break;
592
593             case udp:
594                 if (packet.GetProto() == UDP_PROTO)
595                     portMatchD = (packet.GetSrcPort() >= ln->port1) && (packet.GetSrcPort() <= ln->port2);
596                 break;
597
598             default:
599                 printfd(__FILE__, "Error! Incorrect rule!\n");
600                 break;
601             }
602
603         addrMatchD = (packet.GetSrcIP() & ln->mask) == ln->ip;
604
605         if (!foundD && addrMatchD && portMatchD)
606             {
607             foundD = true;
608             *dirD = ln->dir;
609             //printfd(__FILE__, "Down rule ok! %d\n", ln->dir);
610             //PrintRule(ln->rule);
611             }
612         } //if (!foundD)
613
614     ++ln;
615     }   //while (ln != rules.end())
616
617 if (!foundU)
618     *dirU = DIR_NUM;
619
620 if (!foundD)
621     *dirD = DIR_NUM;
622
623 return;
624 };
625 //-----------------------------------------------------------------------------
626 void TRAFFCOUNTER_IMPL::SetRulesFile(const std::string & fn)
627 {
628 rulesFileName = fn;
629 }
630 //-----------------------------------------------------------------------------
631 bool TRAFFCOUNTER_IMPL::ReadRules(bool test)
632 {
633 //printfd(__FILE__, "TRAFFCOUNTER::ReadRules()\n");
634
635 RULE rul;
636 FILE * f;
637 char str[1024];
638 char tp[100];   // protocol
639 char ta[100];   // address
640 char td[100];   // target direction
641 int r;
642 int lineNumber = 0;
643 f = fopen(rulesFileName.c_str(), "rt");
644
645 if (!f)
646     {
647     printfd(__FILE__, "TRAFFCOUNTER_IMPL::ReadRules() - File '%s' cannot be opened.\n", rulesFileName.c_str());
648     WriteServLog("File '%s' cannot be oppened.", rulesFileName.c_str());
649     return true;
650     }
651
652 while (fgets(str, 1023, f))
653     {
654     lineNumber++;
655     if (str[strspn(str," \t")] == '#' || str[strspn(str," \t")] == '\n')
656         {
657         continue;
658         }
659
660     r = sscanf(str,"%s %s %s", tp, ta, td);
661     if (r != 3)
662         {
663         printfd(__FILE__, "TRAFFCOUNTER_IMPL::ReadRules() - Error in file '%s' at line %d. There must be 3 parameters.\n", rulesFileName.c_str(), lineNumber);
664         WriteServLog("Error in file '%s' at line %d. There must be 3 parameters.", rulesFileName.c_str(), lineNumber);
665         fclose(f);
666         return true;
667         }
668
669     rul.proto = 0xff;
670     rul.dir = 0xff;
671
672     for (int i = 0; i < PROTOMAX; i++)
673         {
674         if (strcasecmp(tp, protoName[i]) == 0)
675             rul.proto = i;
676         }
677
678     for (int i = 0; i < DIR_NUM + 1; i++)
679         {
680         if (td == dirName[i])
681             rul.dir = i;
682         }
683
684     if (rul.dir == 0xff || rul.proto == 0xff)
685         {
686         printfd(__FILE__, "TRAFFCOUNTER_IMPL::ReadRules() - Error in file '%s' at line %d.\n", rulesFileName.c_str(), lineNumber);
687         WriteServLog("Error in file %s. Line %d.",
688                      rulesFileName.c_str(), lineNumber);
689         fclose(f);
690         return true;
691         }
692
693     if (ParseAddress(ta, &rul) != 0)
694         {
695         printfd(__FILE__, "TRAFFCOUNTER_IMPL::ReadRules() - Error in file '%s' at line %d. Error in adress.\n", rulesFileName.c_str(), lineNumber);
696         WriteServLog("Error in file %s. Error in adress. Line %d.",
697                      rulesFileName.c_str(), lineNumber);
698         fclose(f);
699         return true;
700         }
701     if (!test)
702         rules.push_back(rul);
703     //PrintRule(rul);
704     }
705
706 fclose(f);
707
708 // Adding lastest rule: ALL 0.0.0.0/0 NULL
709 rul.dir = DIR_NUM; //NULL
710 rul.ip = 0;  //0.0.0.0
711 rul.mask = 0;
712 rul.port1 = 0;
713 rul.port2 = 65535;
714 rul.proto = all;
715
716 if (!test)
717     rules.push_back(rul);
718
719 //PrintRule(rul);
720
721 return false;
722 }
723 //-----------------------------------------------------------------------------
724 int TRAFFCOUNTER_IMPL::Reload()
725 {
726 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
727
728 if (ReadRules(true))
729     {
730     printfd(__FILE__, "TRAFFCOUNTER_IMPL::Reload() - Failed to reload rules.\n");
731     WriteServLog("TRAFFCOUNTER: Cannot reload rules. Errors found.");
732     return -1;
733     }
734
735 FreeRules();
736 ReadRules();
737 printfd(__FILE__, "TRAFFCOUNTER_IMPL::Reload() -  Reload rules successfull.\n");
738 WriteServLog("TRAFFCOUNTER: Reload rules successfull.");
739 return 0;
740 }
741 //-----------------------------------------------------------------------------
742 bool TRAFFCOUNTER_IMPL::ParseAddress(const char * ta, RULE * rule) const
743 {
744 char addr[50], mask[20], port1[20], port2[20], ports[40];
745
746 int len = strlen(ta);
747 char n = 0;
748 int i, p;
749 memset(addr, 0, sizeof(addr));
750 for (i = 0; i < len; i++)
751     {
752     if (ta[i] == '/' || ta[i] == ':')
753         {
754         addr[i] = 0;
755         n = ta[i];
756         break;
757         }
758     addr[i] = ta[i];
759     n = 0;
760     }
761 addr[i + 1] = 0;
762 p = i + 1;
763
764 if (n == '/')
765     {
766     // mask
767     for (; i < len; i++)
768         {
769         if (ta[i] == ':')
770             {
771             mask[i - p] = 0;
772             n = ':';
773             break;
774             }
775         mask[i - p] = ta[i];
776         }
777     mask[i - p] = 0;
778     }
779 else
780     {
781     strcpy(mask, "32");
782     }
783
784 p = i + 1;
785 i++;
786
787 if (n == ':')
788     {
789     // port
790     if (!(rule->proto == tcp || rule->proto == udp || rule->proto == tcp_udp))
791         {
792         printfd(__FILE__, "TRAFFCOUNTER_IMPL::ParseAddress() - No ports specified for this protocol.\n");
793         WriteServLog("No ports specified for this protocol.");
794         return true;
795         }
796
797     for (; i < len; i++)
798         ports[i - p] = ta[i];
799
800     ports[i - p] = 0;
801     }
802 else
803     {
804     strcpy(ports, "0-65535");
805     }
806
807 char *sss;
808 char pts[100];
809 strcpy(pts, ports);
810
811 if ((sss = strchr(ports, '-')) != NULL)
812     {
813     strncpy(port1, ports, int(sss-ports));
814     port1[int(sss - ports)] = 0;
815     strcpy(port2, sss + 1);
816     }
817 else
818     {
819     strcpy(port1, ports);
820     strcpy(port2, ports);
821     }
822
823 // Convert strings to mask, ports and IP
824 int prt1, prt2, msk;
825 unsigned ip;
826 char *res;
827
828 msk = strtol(mask, &res, 10);
829 if (*res != 0)
830     return true;
831
832 prt1 = strtol(port1, &res, 10);
833 if (*res != 0)
834     return true;
835
836 prt2 = strtol(port2, &res, 10);
837 if (*res != 0)
838     return true;
839
840 int r = inet_aton(addr, (struct in_addr*)&ip);
841 if (r == 0)
842     return true;
843
844 rule->ip = ip;
845 rule->mask = CalcMask(msk);
846 //msk = 1;
847 //printfd(__FILE__, "msk=%d mask=%08X   mask=%08X\n", msk, rule->mask, (0xFFffFFff << (32 - msk)));
848
849 if ((ip & rule->mask) != ip)
850     {
851     printfd(__FILE__, "TRAFFCOUNTER_IMPL::ParseAddress() - Address does'n match mask.\n");
852     WriteServLog("Address does'n match mask.");
853     return true;
854     }
855
856 rule->port1 = prt1;
857 rule->port2 = prt2;
858
859 return false;
860 }
861 //-----------------------------------------------------------------------------
862 uint32_t TRAFFCOUNTER_IMPL::CalcMask(uint32_t msk) const
863 {
864 if (msk >= 32) return 0xFFffFFff;
865 if (msk == 0) return 0;
866 return htonl(0xFFffFFff << (32 - msk));
867 }
868 //---------------------------------------------------------------------------
869 void TRAFFCOUNTER_IMPL::FreeRules()
870 {
871 rules.clear();
872 }
873 //-----------------------------------------------------------------------------
874 void TRAFFCOUNTER_IMPL::PrintRule(RULE rule) const
875 {
876 printf("%15s   ", inet_ntostring(rule.ip).c_str());
877 printf("mask=%08X ", rule.mask);
878 printf("port1=%5d ", rule.port1);
879 printf("port2=%5d ", rule.port2);
880 switch (rule.proto)
881     {
882     case 0:
883         printf("TCP     ");
884         break;
885     case 1:
886         printf("UDP     ");
887         break;
888     case 2:
889         printf("ICMP    ");
890         break;
891     case 3:
892         printf("TCP_UDP ");
893         break;
894     case 4:
895         printf("ALL     ");
896         break;
897     }
898 printf("dir=%d \n", rule.dir);
899 return;
900 }
901 //-----------------------------------------------------------------------------
902 void TRAFFCOUNTER_IMPL::SetMonitorDir(const std::string & monitorDir)
903 {
904 TRAFFCOUNTER_IMPL::monitorDir = monitorDir;
905 monitoring = (monitorDir != "");
906 }
907 //-----------------------------------------------------------------------------