dnsmasq-log.pl 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. #!/usr/bin/perl
  2. #
  3. # Copyright (C) Roman Dmitiriev, rnd@rajven.ru
  4. #
  5. use FindBin '$Bin';
  6. use lib "$Bin/";
  7. use Data::Dumper;
  8. use Rstat::config;
  9. use Rstat::main;
  10. use Rstat::mysql;
  11. use Rstat::net_utils;
  12. use strict;
  13. use warnings;
  14. use Getopt::Long;
  15. use Proc::Daemon;
  16. use Cwd;
  17. use Net::Netmask;
  18. use File::Spec::Functions;
  19. use File::Copy qw(move);
  20. use Text::Iconv;
  21. my $pf = '/var/run/dnsmasq-log.pid';
  22. my $log='/var/lib/dnsmasq/dnsmasq.log';
  23. my $daemon = Proc::Daemon->new(
  24. pid_file => $pf,
  25. work_dir => $HOME_DIR
  26. );
  27. # are you running? Returns 0 if not.
  28. my $pid = $daemon->Status($pf);
  29. my $daemonize = 1;
  30. GetOptions(
  31. 'daemon!' => \$daemonize,
  32. "help" => \&usage,
  33. "reload" => \&reload,
  34. "restart" => \&restart,
  35. "start" => \&run,
  36. "status" => \&status,
  37. "stop" => \&stop
  38. ) or &usage;
  39. exit(0);
  40. sub stop {
  41. if ($pid) {
  42. print "Stopping pid $pid...";
  43. if ($daemon->Kill_Daemon($pf)) {
  44. print "Successfully stopped.\n";
  45. } else {
  46. print "Could not find $pid. Was it running?\n";
  47. }
  48. } else {
  49. print "Not running, nothing to stop.\n";
  50. }
  51. }
  52. sub status {
  53. if ($pid) {
  54. print "Running with pid $pid.\n";
  55. } else {
  56. print "Not running.\n";
  57. }
  58. }
  59. sub run {
  60. if (!$pid) {
  61. print "Starting...";
  62. if ($daemonize) {
  63. # when Init happens, everything under it runs in the child process.
  64. # this is important when dealing with file handles, due to the fact
  65. # Proc::Daemon shuts down all open file handles when Init happens.
  66. # Keep this in mind when laying out your program, particularly if
  67. # you use filehandles.
  68. $daemon->Init;
  69. }
  70. setpriority(0,0,19);
  71. my $converter = Text::Iconv->new("cp866", "utf8");
  72. while (1) {
  73. eval {
  74. # Create new database handle. If we can't connect, die()
  75. system('touch "'.$log.'"');
  76. my $hdb = DBI->connect("dbi:mysql:database=$DBNAME;host=$DBHOST","$DBUSER","$DBPASS");
  77. if ( !defined $hdb ) { die "Cannot connect to mySQL server: $DBI::errstr\n"; }
  78. open(DNSMASQ, "tail -n 0 -F $log |") || die "$log not found!";
  79. while (my $logline = <DNSMASQ>) {
  80. next unless defined $logline;
  81. chomp($logline);
  82. log_info("GET CLIENT REQUEST: $logline");
  83. my ($type,$mac,$ip,$hostname,$tags,$sup_hostname,$old_hostname) = split (/\;/, $logline);
  84. next if (!$type);
  85. next if ($type!~/(old|add|del)/i);
  86. if (time()-$last_refresh_config>=60) { init_option($hdb); }
  87. my $client_hostname='UNDEFINED';
  88. if ($hostname) { $client_hostname=$hostname; } else {
  89. if ($sup_hostname) { $client_hostname=$sup_hostname; } else {
  90. if ($old_hostname) { $client_hostname=$old_hostname; }
  91. }
  92. }
  93. my $auth_network = $office_networks->match_string($ip);
  94. if (!$auth_network) {
  95. log_error("Unknown network in dhcp request! IP: $ip");
  96. next;
  97. }
  98. my $utf_client_hostname = $converter->convert($client_hostname);
  99. log_debug(uc($type).">>");
  100. log_debug("MAC: ".$mac);
  101. log_debug("IP: ".$ip);
  102. log_debug("TAGS: ".$tags);
  103. log_debug("HOSTNAME: ".$client_hostname);
  104. log_debug("UTF8 HOSTNAME: ".$utf_client_hostname);
  105. log_debug("END GET");
  106. my $ip_aton=StrToIp($ip);
  107. $mac=mac_splitted($mac);
  108. if ($type eq 'add') {
  109. log_info("Check for new auth...");
  110. resurrection_auth($hdb,$ip,$mac,$type);
  111. }
  112. my $auth_record = get_custom_record($hdb,'SELECT * FROM User_auth WHERE ip="'.$ip.'" and mac="'.$mac.'" and deleted=0 ORDER BY last_found DESC');
  113. my $auth_id = $auth_record->{id};
  114. my $ad_zone = get_option($hdb,33);
  115. my $ad_dns = get_option($hdb,3);
  116. $update_hostname_from_dhcp = get_option($hdb,46) || 0;
  117. my $subnets_dhcp = get_subnets_ref($hdb);
  118. my $enable_ad_dns_update = ($ad_zone and $ad_dns and $update_hostname_from_dhcp);
  119. log_debug("Subnet: $auth_network");
  120. log_debug("DNS update flags - zone: $ad_zone dns: $ad_dns config: $update_hostname_from_dhcp subnet: $subnets_dhcp->{$auth_network}->{dhcp_update_hostname}");
  121. my $maybe_update_dns=(($type=~/add/i or $type=~/old/i) and $utf_client_hostname and $utf_client_hostname !~/UNDEFINED/i and $enable_ad_dns_update and $subnets_dhcp->{$auth_network}->{dhcp_update_hostname});
  122. if ($maybe_update_dns) {
  123. log_debug("DNS update enabled.");
  124. #update dns block
  125. my $fqdn_static;
  126. if ($auth_record->{dns_name}) {
  127. $fqdn_static=lc($auth_record->{dns_name});
  128. if ($fqdn_static!~/$ad_zone$/i) {
  129. $fqdn_static=~s/\.$//;
  130. $fqdn_static=lc($fqdn_static.'.'.$ad_zone);
  131. }
  132. }
  133. my $fqdn=lc(trim($utf_client_hostname));
  134. if ($fqdn!~/$ad_zone$/i) {
  135. $fqdn=~s/\.$//;
  136. $fqdn=lc($fqdn.'.'.$ad_zone);
  137. }
  138. db_log_debug($hdb,"FOUND Auth_id: $auth_id dns_name: $fqdn_static dhcp_hostname: $fqdn");
  139. #check exists static dns name
  140. my $static_exists = 0;
  141. my $dynamic_exists = 0;
  142. my $static_ok = 0;
  143. my $dynamic_ok = 0;
  144. my $static_ref;
  145. my $dynamic_ref;
  146. if ($fqdn_static ne '') {
  147. my @dns_record=ResolveNames($fqdn_static);
  148. $static_exists = (scalar @dns_record>0);
  149. if ($static_exists) {
  150. $static_ref = join(' ',@dns_record);
  151. foreach my $dns_a (@dns_record) {
  152. if ($dns_a=~/^$ip$/) { $static_ok = $dns_a; }
  153. }
  154. }
  155. } else { $static_ok = 1; }
  156. if ($fqdn ne '') {
  157. my @dns_record=ResolveNames($fqdn);
  158. $dynamic_exists = (scalar @dns_record>0);
  159. if ($dynamic_exists) {
  160. $dynamic_ref = join(' ',@dns_record);
  161. foreach my $dns_a (@dns_record) {
  162. if ($dns_a=~/^$ip$/) { $dynamic_ok = $dns_a; }
  163. }
  164. }
  165. }
  166. if ($fqdn_static ne '') {
  167. if (!$static_ok) {
  168. db_log_info($hdb,"Static record mismatch! Expected $fqdn_static => $ip, recivied: $static_ref");
  169. if (!$static_exists) {
  170. db_log_info($hdb,"Static dns hostname defined but not found. Create it ($fqdn_static => $ip)!");
  171. update_ad_hostname($fqdn_static,$ip,$ad_zone,$ad_dns);
  172. }
  173. } else { db_log_debug($hdb,"Static record for $fqdn_static [$static_ok] correct."); }
  174. }
  175. if ($fqdn ne '' and $dynamic_ok ne '') { db_log_debug($hdb,"Dynamic record for $fqdn [$dynamic_ok] correct. No changes required."); }
  176. if ($fqdn ne '' and !$dynamic_ok) {
  177. #log only to file!!!
  178. log_error($hdb,"Dynamic record mismatch! Expected: $fqdn => $ip, recivied: $dynamic_ref. Checking the status.");
  179. #check exists hostname
  180. my $another_hostname_exists = 0;
  181. my $hostname_filter = ' LOWER(dns_name)="'.lc($utf_client_hostname).'"';
  182. if ($fqdn_static ne '' and $fqdn !~/$fqdn_static/) { $hostname_filter = $hostname_filter . ' or LOWER(dns_name)="'.lc($auth_record->{dns_name}).'"'; }
  183. #check exists another records with some static hostname
  184. my $name_record = get_custom_record($hdb,'SELECT * FROM User_auth WHERE id<>'.$auth_id.' and deleted=0 and ('.$hostname_filter.') ORDER BY last_found DESC');
  185. if ($name_record->{id}) { $another_hostname_exists = 1; }
  186. if (!$another_hostname_exists) {
  187. if ($fqdn_static and $fqdn_static ne '') {
  188. if ($fqdn_static!~/$fqdn/) {
  189. db_log_info($hdb,"Hostname from dhcp request $fqdn differs from static dns hostanme $fqdn_static. Ignore dynamic binding!");
  190. # update_ad_hostname($fqdn,$ip,$ad_zone,$ad_dns);
  191. }
  192. } else {
  193. db_log_info($hdb,"Static dns hostname not defined. Create dns record by dhcp request. $fqdn => $ip");
  194. update_ad_hostname($fqdn,$ip,$ad_zone,$ad_dns);
  195. }
  196. } else {
  197. db_log_error($hdb,"Found another record with some hostname id: $name_record->{id} ip: $name_record->{ip} hostname: $name_record->{dns_hostname}. Skip update.");
  198. }
  199. }
  200. #end update dns block
  201. } else {
  202. db_log_debug($hdb,"FOUND Auth_id: $auth_id");
  203. }
  204. if ($type=~/add/i and $utf_client_hostname and $utf_client_hostname !~/UNDEFINED/i) {
  205. my $auth_rec;
  206. $auth_rec->{dhcp_hostname} = $utf_client_hostname;
  207. update_record($hdb,'User_auth',$auth_rec,"id=$auth_id");
  208. }
  209. if ($hotspot_networks->match_string($ip) and $ignore_hotspot_dhcp_log) { next; }
  210. if ($ignore_update_dhcp_event and $type=~/old/i) { next; }
  211. if ($type=~/(old|del)/i) {
  212. my $auth_rec;
  213. $auth_rec->{dhcp_action}=$type;
  214. $auth_rec->{dhcp_time}=GetNowTime();
  215. update_record($hdb,'User_auth',$auth_rec,"id=$auth_id");
  216. }
  217. my $dhcp_log;
  218. $dhcp_log->{auth_id} = $auth_id;
  219. $dhcp_log->{ip} = $ip;
  220. $dhcp_log->{ip_int} = $ip_aton;
  221. $dhcp_log->{mac} = $mac;
  222. $dhcp_log->{action} = $type;
  223. insert_record($hdb,'dhcp_log',$dhcp_log);
  224. }
  225. close DNSMASQ;
  226. };
  227. if ($@) { log_error("Exception found: $@"); }
  228. }
  229. } else {
  230. print "Already Running with pid $pid\n";
  231. }
  232. }
  233. sub usage {
  234. print "usage: dnsmasq-log.pl (start|stop|status|restart)\n";
  235. exit(0);
  236. }
  237. sub reload {
  238. print "reload process not implemented.\n";
  239. }
  240. sub restart {
  241. stop;
  242. run;
  243. }