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