garbage.pl 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. #!/usr/bin/perl
  2. #
  3. # Copyright (C) Roman Dmitiriev, rnd@rajven.ru
  4. #
  5. use utf8;
  6. use English;
  7. use base;
  8. use FindBin '$Bin';
  9. use lib "$Bin/";
  10. use strict;
  11. use DBI;
  12. use Date::Parse;
  13. use Rstat::config;
  14. use Rstat::mysql;
  15. use Rstat::net_utils;
  16. use DateTime;
  17. use Fcntl qw(:flock);
  18. open(SELF,"<",$0) or die "Cannot open $0 - $!";
  19. flock(SELF, LOCK_EX|LOCK_NB) or exit 1;
  20. db_log_info($dbh,'Garbage started.');
  21. sub is_dhcp_pool {
  22. my $pools = shift;
  23. my $ip_int = shift;
  24. foreach my $subnet (keys %{$pools}) {
  25. #print "net: $subnet ip: $ip_int pool: $pools->{$subnet}->{first_ip} .. $pools->{$subnet}->{last_ip}\n";
  26. if ($ip_int <= $pools->{$subnet}->{last_ip} and $ip_int>= $pools->{$subnet}->{first_ip}) { return $subnet; }
  27. }
  28. return 0;
  29. }
  30. #unblock users
  31. my ($sec,$min,$hour,$day,$month,$year,$zone) = localtime(time());
  32. my $history_sql;
  33. my $history_rf;
  34. my %nets;
  35. my %dhcp_conf;
  36. foreach my $net (@office_network_list) {
  37. my $scope_name=$net;
  38. $scope_name =~s/\/\d+$//g;
  39. $nets{$scope_name}= new Net::Patricia;
  40. $nets{$scope_name}->add_string($net);
  41. }
  42. my $now = DateTime->now(time_zone=>'local');
  43. $now->set(day=>1);
  44. my $month_start=$dbh->quote($now->ymd("-")." 00:00:00");
  45. my $month_dur = DateTime::Duration->new( months => 1 );
  46. my $next_month = $now + $month_dur;
  47. $next_month->set(day=>1);
  48. my $month_stop = $dbh->quote($next_month->ymd("-")." 00:00:00");
  49. my $dhcp_networks = new Net::Patricia;
  50. my @subnets=get_records_sql($dbh,'SELECT * FROM subnets WHERE office=1 AND dhcp=1 AND vpn=0 ORDER BY ip_int_start');
  51. foreach my $subnet (@subnets) {
  52. $dhcp_networks->add_string($subnet->{subnet});
  53. my $subnet_name = $subnet->{subnet};
  54. $subnet_name=~s/\/\d+$//g;
  55. $dhcp_conf{$subnet_name}->{first_ip}=$subnet->{dhcp_start};
  56. $dhcp_conf{$subnet_name}->{last_ip}=$subnet->{dhcp_stop};
  57. }
  58. if ($day==1) {
  59. do_sql($dbh,"Update User_list set blocked=0");
  60. do_sql($dbh,"Update User_auth set blocked=0, changed=1 WHERE blocked=1 and deleted=0");
  61. db_log_verbose($dbh,"Amnistuyemo all blocked user by traffic for a month");
  62. } else {
  63. #month stat
  64. my $month_sql="SELECT User_list.id, User_list.login, SUM( traf_all ) AS traf_sum, User_list.month_quota as uquota
  65. FROM ( SELECT User_stats.auth_id, SUM( byte_in + byte_out ) AS traf_all FROM User_stats
  66. WHERE User_stats.`timestamp`>=$month_start AND User_stats.`timestamp`< $month_stop
  67. GROUP BY User_stats.auth_id ) AS V, User_auth, User_list
  68. WHERE V.auth_id = User_auth.id AND User_auth.user_id = User_list.id and User_list.blocked=1 GROUP BY login";
  69. my @month_stats = get_records_sql($dbh,$month_sql);
  70. foreach my $row (@month_stats) {
  71. my $m_quota=$row->{uquota}*$KB*$KB;
  72. next if ($m_quota < $row->{traf_sum});
  73. db_log_info($dbh,"Amnistuyemo blocked user $row->{login} [$row->{id}] by traffic for a day");
  74. do_sql($dbh,"UPDATE User_list set blocked=0 WHERE id=$row->{id}");
  75. do_sql($dbh,"UPDATE User_auth set blocked=0, changed=1 WHERE user_id=$row->{id}");
  76. }
  77. }
  78. #clean temporary dhcp leases & connections only for dhcp pool ip
  79. my $users_sql = "SELECT * FROM User_auth WHERE deleted=0 AND (`ou_id`=".$default_user_ou_id." OR `ou_id`=".$default_hotspot_ou_id.")";
  80. my @users_auth = get_records_sql($dbh,$users_sql);
  81. foreach my $row (@users_auth) {
  82. next if (!is_dhcp_pool(\%dhcp_conf,$row->{ip_int}));
  83. my $last_dhcp_time = GetUnixTimeByStr($row->{dhcp_time});
  84. if ($dhcp_networks->match_string($row->{ip})) {
  85. my $clean_dhcp_time = $last_dhcp_time + 60*$dhcp_networks->match_string($row->{ip});
  86. if (time() - $clean_dhcp_time>0) {
  87. db_log_verbose($dbh,"Clean overdue dhcp leases for ip: $row->{ip} id: $row->{id} last dhcp: $row->{dhcp_time} clean time: ".GetTimeStrByUnixTime($clean_dhcp_time)." now: ".GetNowTime());
  88. # do_sql($dbh,"DELETE FROM connections WHERE auth_id='".$row->{id}."'");
  89. do_sql($dbh,"UPDATE User_auth SET deleted=1 WHERE id='".$row->{id}."'");
  90. my $u_count=get_count_records($dbh,'User_auth','deleted=0 and user_id='.$row->{user_id});
  91. if (!$u_count) {
  92. delete_record($dbh,"User_list","id=".$row->{'user_id'});
  93. db_log_verbose($dbh,"Remove dynamic user id: $row->{'user_id'} by dhcp lease timeout");
  94. }
  95. }
  96. }
  97. }
  98. $now = DateTime->now(time_zone=>'local');
  99. my $day_dur = DateTime::Duration->new( days => $history_dhcp );
  100. my $clean_date = $now - $day_dur;
  101. my $clean_str = $dbh->quote($clean_date->ymd("-")." 00:00:00");
  102. #clean dhcp log
  103. do_sql($dbh,"DELETE FROM dhcp_log WHERE `timestamp` < $clean_str" );
  104. db_log_verbose($dbh,"Clean dhcp leases for all older that ".$clean_str);
  105. ##### clean old connections ########
  106. $day_dur = DateTime::Duration->new( days => $connections_history );
  107. $clean_date = $now - $day_dur;
  108. $clean_str = $dbh->quote($clean_date->ymd("-")." 00:00:00");
  109. $users_sql = "SELECT id FROM User_auth WHERE `last_found` < $clean_str and last_found>0";
  110. db_log_debug($dbh,$users_sql) if ($debug);
  111. @users_auth=get_records_sql($dbh,$users_sql);
  112. foreach my $row (@users_auth) {
  113. db_log_debug($dbh,"Clear old connection for user_auth ".$row->{id}) if ($debug);
  114. do_sql($dbh,"DELETE FROM connections WHERE auth_id='".$row->{id}."'");
  115. }
  116. ##### clean dup connections ########
  117. my $conn_sql = "SELECT id,port_id,auth_id FROM connections order by port_id";
  118. my @conn_ref = get_records_sql($dbh,$conn_sql);
  119. my $old_port_id=0;
  120. my $old_auth_id=0;
  121. foreach my $row (@conn_ref) {
  122. my $c_id = $row->{id};
  123. my $c_port_id = $row->{port_id};
  124. my $c_auth_id = $row->{auth_id};
  125. if (!$c_port_id) { $c_port_id=0; }
  126. if (!$c_auth_id) { $c_auth_id=0; }
  127. if ($old_port_id ==0 or $old_auth_id==0) { $old_port_id=$c_port_id; $old_auth_id=$c_auth_id; next; }
  128. if ($old_port_id >0 and $old_port_id != $c_port_id) { $old_port_id=$c_port_id; $old_auth_id=$c_auth_id; next; }
  129. if ($old_auth_id >0 and $old_auth_id != $c_auth_id) { $old_port_id=$c_port_id; $old_auth_id=$c_auth_id; next; }
  130. do_sql($dbh,"DELETE FROM connections WHERE id='".$c_id."'");
  131. db_log_verbose($dbh,"Remove dup connection $c_id: $c_port_id $c_auth_id");
  132. }
  133. ##### clean empty user account and corresponded devices ################
  134. my $u_sql = "SELECT * FROM User_list as U WHERE (U.ou_id=".$default_hotspot_ou_id." OR U.ou_id=".$default_user_ou_id.") AND (SELECT COUNT(*) FROM User_auth WHERE User_auth.deleted=0 AND User_auth.user_id = U.id)=0";
  135. my @u_ref = get_records_sql($dbh,$u_sql);
  136. foreach my $row (@u_ref) {
  137. do_sql($dbh,"DELETE FROM User_list WHERE id='".$row->{id}."'");
  138. db_log_verbose($dbh,"Remove empty user id: $row->{id} login: $row->{login}");
  139. #delete binded device
  140. my $user_device = get_record_sql($dbh,"SELECT * FROM devices WHERE user_id=".$row->{id});
  141. if ($user_device) {
  142. db_log_verbose($dbh,"Remove corresponded device id: $user_device->{id} name: $user_device->{device_name}");
  143. unbind_ports($dbh, $user_device->{id});
  144. do_sql($dbh, "DELETE FROM connections WHERE device_id=".$user_device->{id});
  145. do_sql($dbh, "DELETE FROM device_l3_interfaces WHERE device_id=".$user_device->{id});
  146. do_sql($dbh, "DELETE FROM device_ports WHERE device_id=".$user_device->{id});
  147. delete_record($dbh, "devices", "id=".$user_device->{id});
  148. }
  149. }
  150. ##### unknown mac clean ############
  151. $users_sql = "SELECT mac FROM User_auth WHERE deleted=0";
  152. @users_auth = get_records_sql($dbh,$users_sql);
  153. foreach my $row (@users_auth) {
  154. next if (!$row->{mac});
  155. do_sql($dbh,"DELETE FROM Unknown_mac WHERE mac='".mac_simplify($row->{mac})."'");
  156. }
  157. ##### traffic detail ######
  158. $day_dur = DateTime::Duration->new( days => $history );
  159. $clean_date = $now - $day_dur;
  160. $clean_str = $dbh->quote($clean_date->ymd("-")." 00:00:00");
  161. db_log_verbose($dbh,"Clean traffic detail older that ".$clean_str);
  162. #clean old traffic detail
  163. do_sql($dbh,"DELETE FROM Traffic_detail WHERE `timestamp` < $clean_str" );
  164. ##### log ######
  165. $day_dur = DateTime::Duration->new( days => $history_log_day );
  166. $clean_date = $now - $day_dur;
  167. $clean_str = $dbh->quote($clean_date->ymd("-")." 00:00:00");
  168. db_log_verbose($dbh,"Clean worklog older that ".$clean_str);
  169. do_sql($dbh,"DELETE FROM syslog WHERE `timestamp` < $clean_str" );
  170. #clean debug logs older than 2 days
  171. $day_dur = DateTime::Duration->new( days => 2 );
  172. $clean_date = $now - $day_dur;
  173. $clean_str = $dbh->quote($clean_date->ymd("-")." 00:00:00");
  174. db_log_verbose($dbh,"Clean debug worklog older that ".$clean_str);
  175. do_sql($dbh,"DELETE FROM syslog WHERE level>3 AND `timestamp` < $clean_str" );
  176. ##### remote syslog ######
  177. $day_dur = DateTime::Duration->new( days => $history_syslog_day );
  178. $clean_date = $now - $day_dur;
  179. $clean_str = $dbh->quote($clean_date->ymd("-")." 00:00:00");
  180. db_log_verbose($dbh,"Clean syslog older that ".$clean_str);
  181. do_sql($dbh,"DELETE FROM remote_syslog WHERE `date` < $clean_str" );
  182. ##### Traffic stats ######
  183. $day_dur = DateTime::Duration->new( days => $history_trafstat_day );
  184. $clean_date = $now - $day_dur;
  185. $clean_str = $dbh->quote($clean_date->ymd("-")." 00:00:00");
  186. db_log_verbose($dbh,"Clean traffic statistics older that ".$clean_str);
  187. do_sql($dbh,"DELETE FROM User_stats WHERE `timestamp` < $clean_str" );
  188. ##### Traffic stats full ######
  189. my $iptraf_history = $config_ref{traffic_ipstat_history} || 30;
  190. $day_dur = DateTime::Duration->new( days => $iptraf_history );
  191. $clean_date = $now - $day_dur;
  192. $clean_str = $dbh->quote($clean_date->ymd("-")." 00:00:00");
  193. db_log_verbose($dbh,"Clean traffic full statistics older that ".$clean_str);
  194. do_sql($dbh,"DELETE FROM User_stats_full WHERE `timestamp` < $clean_str" );
  195. #### clean unknown user ip
  196. do_sql($dbh,"DELETE FROM User_auth WHERE (mac is NULL or mac='') and deleted=1");
  197. #### save location changes
  198. my %connections;
  199. my @connections_list=get_records_sql($dbh,"SELECT * FROM connections ORDER BY auth_id");
  200. foreach my $connection (@connections_list) {
  201. next if (!$connection);
  202. $connections{$connection->{auth_id}}=$connection;
  203. }
  204. my $auth_sql="SELECT * FROM User_auth WHERE mac IS NOT NULL AND mac !='' AND deleted=0 ORDER BY last_found DESC";
  205. my %auth_table;
  206. my @auth_full_list=get_records_sql($dbh,$auth_sql);
  207. foreach my $auth (@auth_full_list) {
  208. next if (!$auth);
  209. my $auth_mac=mac_simplify($auth->{mac});
  210. next if (exists $auth_table{$auth_mac});
  211. next if (!exists $connections{$auth->{id}});
  212. $auth_table{$auth_mac}=1;
  213. my $h_sql = "SELECT * FROM mac_history WHERE mac='".$auth_mac."' ORDER BY `timestamp` DESC";
  214. my $history = get_record_sql($dbh,$h_sql);
  215. if (!$history) {
  216. #add record to history
  217. my $cur_conn = $connections{$auth->{id}};
  218. my $new;
  219. $new->{device_id}=$cur_conn->{device_id};
  220. $new->{port_id}=$cur_conn->{port_id};
  221. $new->{auth_id}=$auth->{id};
  222. $new->{ip}=$auth->{ip};
  223. $new->{mac}=$auth_mac;
  224. $new->{timestamp}=$auth->{last_found};
  225. db_log_info($dbh,"Auth id: $auth->{id} $auth_mac found at location device_id: $new->{device_id} port_id: $new->{port_id}");
  226. insert_record($dbh,"mac_history",$new);
  227. next;
  228. }
  229. my $cur_conn = $connections{$auth->{id}};
  230. #check record history
  231. if ($history->{device_id} != $cur_conn->{device_id} or $history->{port_id} != $cur_conn->{port_id}) {
  232. #add new record
  233. my $new;
  234. $new->{device_id}=$cur_conn->{device_id};
  235. $new->{port_id}=$cur_conn->{port_id};
  236. $new->{auth_id}=$auth->{id};
  237. $new->{ip}=$auth->{ip};
  238. $new->{mac}=$auth_mac;
  239. $new->{timestamp}=$auth->{last_found};
  240. db_log_info($dbh,"Auth id: $auth->{id} $auth_mac moved to another location device_id: $new->{device_id} port_id: $new->{port_id}");
  241. insert_record($dbh,"mac_history",$new);
  242. }
  243. }
  244. db_log_info($dbh,'Garbage stopped.');
  245. $dbh->disconnect;
  246. exit 0;