Ver Fonte

add dynamic update for dns-records

root há 2 anos atrás
pai
commit
9441000afa

+ 2 - 2
docs/addons/set_dns_record.pl

@@ -52,11 +52,11 @@ if ($h_name) {
     }
 
 db_log_info($dbh,"Manual create dns record $fqdn");
-update_ad_hostname($fqdn,$ip,$ad_zone,$ad_dns,$dbh);
+update_dns_hostname($fqdn,$ip,$ad_zone,$ad_dns,$dbh);
 
 if ($reverse) {
     db_log_info($dbh,"Manual create dns ptr-record $fqdn => $ip");
-    update_ad_ptr($fqdn,$ip,$ad_dns,$dbh);
+    update_dns_ptr($fqdn,$ip,$ad_dns,$dbh);
     }
 
 exit;

+ 0 - 248
docs/addons/socket/dhcp-log.pl

@@ -1,248 +0,0 @@
-#!/usr/bin/perl
-
-#
-# Copyright (C) Roman Dmitiriev, rnd@rajven.ru
-#
-
-# Use socket for logging
-
-use utf8;
-use English;
-use base;
-use FindBin '$Bin';
-use lib "$Bin/";
-use Data::Dumper;
-use eyelib::config;
-use eyelib::main;
-use eyelib::mysql;
-use eyelib::net_utils;
-use strict;
-use warnings;
-use Getopt::Long;
-use Proc::Daemon;
-use POSIX;
-use Cwd;
-use IO::Socket::UNIX qw( SOCK_STREAM );
-use Net::Netmask;
-use File::Spec::Functions;
-use File::Copy qw(move);
-use Text::Iconv;
-
-my $pf = '/var/run/dhcp-log.pid';
-my $socket_path='/var/spool/dhcp-log.socket';
-
-my $mute_time=300;
-
-my $daemon = Proc::Daemon->new(
-        pid_file => $pf,
-        work_dir => $HOME_DIR
-);
-
-# are you running?  Returns 0 if not.
-my $pid = $daemon->Status($pf);
-
-my $daemonize = 1;
-
-GetOptions(
-    'daemon!' => \$daemonize,
-    "help"    => \&usage,
-    "reload"  => \&reload,
-    "restart" => \&restart,
-    "start"   => \&run,
-    "status"  => \&status,
-    "stop"    => \&stop
-) or &usage;
-
-exit(0);
-
-sub stop {
-        if ($pid) {
-                print "Stopping pid $pid...";
-                if ($daemon->Kill_Daemon($pf)) {
-                        print "Successfully stopped.\n";
-                } else {
-                        print "Could not find $pid.  Was it running?\n";
-                }
-         } else {
-                print "Not running, nothing to stop.\n";
-         }
-}
-
-sub status {
-        if ($pid) {
-                print "Running with pid $pid.\n";
-        } else {
-                print "Not running.\n";
-        }
-}
-
-sub run {
-if (!$pid) {
-    print "Starting...";
-    if ($daemonize) {
-        # when Init happens, everything under it runs in the child process.
-        # this is important when dealing with file handles, due to the fact
-        # Proc::Daemon shuts down all open file handles when Init happens.
-        # Keep this in mind when laying out your program, particularly if
-        # you use filehandles.
-        $daemon->Init;
-        }
-
-    setpriority(0,0,19);
-
-    my $converter = Text::Iconv->new("cp866", "utf8");
-
-    while (1) {
-        eval {
-
-        my %leases;
-
-        if (! -e "$socket_path") { mkfifo($socket_path,0622); }
-
-        open(DHCP_SOCKET,$socket_path) || die("Error open fifo socket $socket_path: $!");
-
-        # Create new database handle. If we can't connect, die()
-        my $hdb = DBI->connect("dbi:mysql:database=$DBNAME;host=$DBHOST","$DBUSER","$DBPASS");
-        if ( !defined $hdb ) { die "Cannot connect to mySQL server: $DBI::errstr\n"; }
-
-        while (my $logline = <DHCP_SOCKET>) {
-            next unless defined $logline;
-            chomp($logline);
-            log_verbose("GET CLIENT REQUEST: $logline");
-            my ($type,$mac,$ip,$hostname,$timestamp,$tags,$sup_hostname,$old_hostname) = split (/\;/, $logline);
-            next if (!$type);
-            next if ($type!~/(old|add|del)/i);
-
-            if (exists $leases{$ip} and time()-$leases{$ip}{last_time} <= $mute_time) { next; }
-
-            if (time()-$last_refresh_config>=60) { init_option($hdb); }
-
-            my $client_hostname='UNDEFINED';
-            if ($hostname and $hostname ne "undef") { $client_hostname=$hostname; } else {
-                if ($sup_hostname) { $client_hostname=$sup_hostname; } else {
-                    if ($old_hostname) { $client_hostname=$old_hostname; }
-                    }
-                }
-
-            my $auth_network = $office_networks->match_string($ip);
-            if (!$auth_network) {
-                log_error("Unknown network in dhcp request! IP: $ip");
-                next;
-                }
-
-            if (!$timestamp) { $timestamp=time(); }
-
-            my $dhcp_event_time = GetNowTime($timestamp);
-
-            my $ip_aton=StrToIp($ip);
-            $mac=mac_splitted(isc_mac_simplify($mac));
-
-            my $dhcp_record;
-            $dhcp_record->{mac}=$mac;
-            $dhcp_record->{ip}=$ip;
-            $dhcp_record->{ip_aton}=$ip_aton;
-            $dhcp_record->{hostname}=$client_hostname;
-            $dhcp_record->{tags}=$tags;
-            $dhcp_record->{network}=$auth_network;
-            $dhcp_record->{type}=$type;
-            $dhcp_record->{hostname_utf8}=$converter->convert($client_hostname);
-            $dhcp_record->{timestamp} = $timestamp;
-            $dhcp_record->{last_time} = time();
-            $dhcp_record->{hotspot}=is_hotspot($dbh,$dhcp_record->{ip});
-            $leases{$ip}=$dhcp_record;
-
-            log_debug(uc($type).">>");
-            log_debug("MAC:      ".$dhcp_record->{mac});
-            log_debug("IP:       ".$dhcp_record->{ip});
-            log_debug("TAGS:     ".$dhcp_record->{tags});
-            log_debug("HOSTNAME: ".$dhcp_record->{hostname});
-            log_debug("TYPE:     ".$dhcp_record->{type});
-            log_debug("TIME:     ".$dhcp_event_time);
-            log_debug("UTF8 HOSTNAME: ".$dhcp_record->{hostname_utf8});
-            log_debug("END GET");
-
-            my $auth_record = get_record_sql($hdb,'SELECT * FROM User_auth WHERE ip="'.$dhcp_record->{ip}.'" and mac="'.$mac.'" and deleted=0 ORDER BY last_found DESC');
-	        if (!$auth_record and $type eq 'old' ) { $type='add'; }
-
-            if ($type eq 'add') {
-                my $res_id = resurrection_auth($hdb,$dhcp_record);
-                next if (!$res_id);
-                $auth_record = get_record_sql($hdb,'SELECT * FROM User_auth WHERE id='.$res_id);
-                db_log_info($hdb,"Check for new auth. Found id: $res_id",$res_id);
-                } else { $auth_record = get_record_sql($hdb,'SELECT * FROM User_auth WHERE ip="'.$dhcp_record->{ip}.'" and mac="'.$mac.'" and deleted=0 ORDER BY last_found DESC'); }
-
-            my $auth_id = $auth_record->{id};
-	        my $auth_ou_id = $auth_record->{ou_id};
-
-            update_dns_record($hdb,$dhcp_record,$auth_record);
-
-            if ($type=~/add/i and $dhcp_record->{hostname_utf8} and $dhcp_record->{hostname_utf8} !~/UNDEFINED/i) {
-                my $auth_rec;
-                $auth_rec->{dhcp_hostname} = $dhcp_record->{hostname_utf8};
-                $auth_rec->{dhcp_time}=$dhcp_event_time;
-                db_log_verbose($hdb,"Add lease by dhcp event for dynamic clients id:$auth_id ip: $dhcp_record->{ip}",$auth_id);
-                update_record($hdb,'User_auth',$auth_rec,"id=$auth_id");
-                }
-
-            if ($dhcp_record->{hotspot} and $ignore_hotspot_dhcp_log) { next; }
-
-            if ($ignore_update_dhcp_event and $type=~/old/i) { next; }
-
-            if ($type=~/old/i) {
-                    my $auth_rec;
-                    $auth_rec->{dhcp_action}=$type;
-                    $auth_rec->{dhcp_time}=$dhcp_event_time;
-                    db_log_verbose($hdb,"Update lease by dhcp event for dynamic clients id:$auth_id ip: $dhcp_record->{ip}",$auth_id);
-                    update_record($hdb,'User_auth',$auth_rec,"id=$auth_id");
-                }
-
-            if ($type=~/del/i and $auth_id) {
-                if ($auth_record->{dhcp_time} =~ /([0-9]{4})-([0-9]{2})-([0-9]{2}) ([0-9]{2}):([0-9]{2}):([0-9]{2})/) {
-                    my $d_time = mktime($6,$5,$4,$3,$2-1,$1-1900);
-                    if (time()-$d_time>60 and ($auth_ou_id == $default_user_ou_id or $auth_ou_id==$default_hotspot_ou_id)) {
-                        db_log_info($hdb,"Remove user ip record by dhcp release event for dynamic clients id:$auth_id ip: $dhcp_record->{ip}",$auth_id);
-                        my $auth_rec;
-                        $auth_rec->{deleted}="1";
-                        $auth_rec->{dhcp_action}=$type;
-                        $auth_rec->{dhcp_time}=$dhcp_event_time;
-                        update_record($hdb,'User_auth',$auth_rec,"id=$auth_id");
-                        my $u_count=get_count_records($hdb,'User_auth','deleted=0 and user_id='.$auth_record->{'user_id'});
-		        if (!$u_count) {
-				delete_record($hdb,"User_list","id=".$auth_record->{'user_id'});
-	                        db_log_info($hdb,"Remove dynamic user id: $auth_record->{'user_id'} by dhcp request",$auth_id);
-	                        }
-                        }
-                    }
-                }
-
-            my $dhcp_log;
-            $dhcp_log->{auth_id} = $auth_id;
-            $dhcp_log->{ip} = $dhcp_record->{ip};
-            $dhcp_log->{ip_int} = $dhcp_record->{ip_aton};
-            $dhcp_log->{mac} = $dhcp_record->{mac};
-            $dhcp_log->{action} = $type;
-            $dhcp_log->{timestamp} = $dhcp_event_time;
-            insert_record($hdb,'dhcp_log',$dhcp_log);
-            }
-        close DHCP_SOCKET;
-        };
-        if ($@) { log_error("Exception found: $@"); sleep(60); }
-        }
-    } else {
-        print "Already Running with pid $pid\n";
-    }
-}
-
-sub usage {
-    print "usage: dhcp-log.pl (start|stop|status|restart)\n";
-    exit(0);
-}
-
-sub reload {
-    print "reload process not implemented.\n";
-}
-
-sub restart {
-    stop;
-    run;
-}

+ 0 - 14
docs/addons/socket/dhcp-log.service

@@ -1,14 +0,0 @@
-[Unit]
-Description=Write dhcp events to Rstat
-After=network.target mariadb.service
-Before=dnsmasq.service dhcpd.service
-
-[Service]
-Type=forking
-ExecStart=/opt/Eye/scripts/dhcp-log.pl --start
-PIDFile=/var/run/dhcp-log.pid
-RestartSec=30
-Restart=on-failure
-
-[Install]
-WantedBy=multi-user.target

+ 0 - 6
docs/addons/socket/dnsmasq-hook.sh

@@ -1,6 +0,0 @@
-#!/bin/bash
-
-time=$(date +%s)
-echo "$1;$2;$3;$4;${time};${DNSMASQ_TAGS};${DNSMASQ_SUPPLIED_HOSTNAME};${DNSMASQ_OLD_HOSTNAME}" >>/var/spool/dhcp-log.socket &
-
-exit

+ 0 - 12
docs/addons/socket/dnsmasq.service

@@ -1,12 +0,0 @@
-[Unit]
-Description=DNS caching server
-After=network.target dhcp-log.service
-PartOf=dhcp-log.service
-
-[Service]
-ExecStart=/usr/sbin/dnsmasq -k
-RestartSec=30
-Restart=on-failure
-
-[Install]
-WantedBy=multi-user.target

+ 4 - 0
docs/bind/gen_key.sh

@@ -0,0 +1,4 @@
+#!/bin/bash
+
+rndc-confgen -a
+

+ 24 - 0
docs/bind/named.conf

@@ -0,0 +1,24 @@
+options {
+        listen-on port 53 { 127.0.0.1; 192.168.1.1; };
+        listen-on-v6 { none; };
+        directory       "/etc/bind";
+        dump-file       "/etc/bind/data/cache_dump.db";
+        statistics-file "/etc/bind/data/named_stats.txt";
+        memstatistics-file "/etc/bind/data/named_mem_stats.txt";
+        allow-query     { 127.0.0.0/8; 192.168.0.0/16; 10.0.0.0/8; };
+//        recursion no;
+        dnssec-validation auto;
+        auth-nxdomain no;
+
+        masterfile-format text;
+};
+
+include "/etc/bind/rndc.key";
+
+controls {
+inet 127.0.0.1 port 953 allow { 127.0.0.1; } keys { "rndc-key"; };
+};
+
+include "/etc/bind/named.conf.default-zones";
+
+include "/etc/bind/named.dynamic";

+ 18 - 7
docs/addons/print-dns-zones.pl → docs/bind/print-dns-zones.pl

@@ -17,14 +17,17 @@ use eyelib::mysql;
 
 setpriority(0,0,19);
 
-my $named_root='/var/named/chroot';
-my $named_db_fullpath=$named_root.'/var/named/master';
-my $named_db_path='/var/named/master';
+my $named_root='';
+my $named_db_fullpath=$named_root.'/etc/bind/masters';
+my $named_db_path='/etc/bind/masters';
 
 my $ns1 = 'ns1';
-my $DNS1=$ns1.'.'.$domain_name;
 
-my $named_conf=$named_root.'/etc/named.dynamic';
+my $DNS1=$config_ref{dns_server};
+
+exit if ($config_ref{dns_server_type!='bind');
+
+my $named_conf=$named_root.'/etc/bind/named.dynamic';
 
 # user auth list
 my @authlist_ref = get_records_sql($dbh,"SELECT id,ip,dns_name FROM User_auth WHERE `ip_int`>0 AND `deleted`=0 ORDER BY ip_int");
@@ -46,18 +49,24 @@ $default_name=~s/\./-/g;
 
 if ($dns_name) {
     $default_name=$dns_name;
+    $default_name =~s/$domain_name$//g;
+    $default_name =~s/\.$/-/g;
     $default_name =~s/_/-/g;
     $default_name =~s/[.]/-/g;
     $default_name =~s/ /-/g;
+    $default_name =~s/-$//g;
     $zones{$domain_name}{$default_name}=$ip;
     }
 
 my @dns_names=get_records_sql($dbh,"SELECT * FROM User_auth_alias WHERE auth_id=$row->{id} ORDER BY alias");
 foreach my $alias (@dns_names) {
         my $dns = $alias->{alias};
+        $dns =~s/$domain_name$//g;
+        $dns =~s/\.$/-/g;
         $dns =~s/_/-/g;
         $dns =~s/[.]/-/g;
         $dns =~s/ /-/g;
+        $dns =~s/-$//g;
         $zones{$domain_name}{$dns}=$ip;
         }
 
@@ -86,6 +95,8 @@ my $zone_name=$ZONE;
 
 if ($ZONE!~/$domain_name/) {
     $reverse=1;
+    #skip reverse dns zone
+    next;
     if ($ZONE=~/([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})/) {
         $zone_name=$3.".".$2.".".$1.".in-addr.arpa";
         } else {
@@ -97,8 +108,8 @@ if ($ZONE!~/$domain_name/) {
 print F2 "zone $zone_name \{\n";
 print F2 "type master;\n";
 print F2 "file \"$named_db_path"."/db.".$ZONE."\";\n";
-#print F2 "allow-update { key rndckey; };\n";
-print F2 "allow-transfer { second; };\n";
+print F2 "allow-update { key rndc-key; };\n";
+#print F2 "allow-transfer { second; };\n";
 print F2 "\};\n";
 print F2 "\n";
 

+ 14 - 12
docs/addons/update-named → docs/bind/update-named

@@ -2,16 +2,18 @@
 
 logger -t named "Refresh named config request"
 
+force=$1
+
 /opt/Eye/scripts/print-dns-zones.pl
 [ $? -ne 0 ] && exit 1
 
 RELOAD=
-ZONELIST=`ls -x -1 /var/named/chroot/var/named/master/db.*.new`
+ZONELIST=`ls -x -1 /etc/bind/masters/db.*.new`
 echo "${ZONELIST}" | while read NS2_DB; do
 NS1_DB=`echo "$NS2_DB" | sed 's/.new$//'`
 [ ! -e $NS1_DB ] && {
     cat $NS2_DB > $NS1_DB
-    chown named:named ${NS1_DB} >/dev/null
+    chown bind:bind ${NS1_DB} >/dev/null
     RELOAD=1
     continue
     }
@@ -30,28 +32,28 @@ echo "dns config $NS1_DB changed."
 cat $NS2_DB > $NS1_DB
 RELOAD=1
 rm -f "${NS2_DB}" >/dev/null
-chown named:named ${NS1_DB} >/dev/null
+chown bind:bind ${NS1_DB} >/dev/null
 done
 
-diff -aqbBfi /var/named/chroot/etc/named.dynamic.new /var/named/chroot/etc/named.dynamic >/dev/null
+diff -aqbBfi /etc/bind/named.dynamic.new /etc/bind/named.dynamic >/dev/null
 [ $? -ne 0 ] && {
     RELOAD=1
-    cat /var/named/chroot/etc/named.dynamic.new >/var/named/chroot/etc/named.dynamic
+    cat /etc/bind/named.dynamic.new >/etc/bind/named.dynamic
     }
 
-if [ -n "${RELOAD}" ]; then
+if [ -n "${RELOAD}" -o -n "${force}" ]; then
     logger -t named "Configuration changed. Check config"
-    /usr/sbin/named-checkconf -t /var/named/chroot/ -z >/dev/null
+    /usr/bin/named-checkconf -t / -z >/dev/null
     if [ $? -eq 0 ]; then
-	logger -t named "Config fine! Restart named"
-        /sbin/service named restart >/dev/null
+        logger -t named "Config fine! Restart named"
+        /usr/bin/systemctl restart named >/dev/null
         fi
     else
-	logger -t named "Config not changed! Skip restart"
+        logger -t named "Config not changed! Skip restart"
     fi
 
-rm -f /var/named/chroot/etc/named.dynamic.new 2>/dev/null
-rm -f /var/named/chroot/var/named/master/db.*.new 2>/dev/null
+rm -f /etc/bind/named.dynamic.new 2>/dev/null
+rm -f /etc/bind/masters/db.*.new 2>/dev/null
 
 logger -t named "done"
 

+ 5 - 0
html/admin/customers/control-options.php

@@ -115,6 +115,11 @@ print_control_submenu($page_url);
                 if ($type == 'bool') {
                     print_qa_select("f_config_value[" . $row['id'] . "]", $option_value);
                 }
+                if (preg_match('/^list;/',$type)) {
+                     $value_list=explode(';',$type);
+                     array_splice($value_list,0,1);
+                     print_list_select("f_config_value[" . $row['id'] . "]", $option_value,$value_list);
+                }
                 print "</td>\n";
                 print "<td colspan=3 class=\"data\">" . $row[$descr_field] . "</td>\n";
                 print "</tr>\n";

+ 26 - 0
html/inc/common.php

@@ -899,6 +899,16 @@ function print_qa_select($qa_name, $qa_value = 0)
     print "</select>\n";
 }
 
+function print_list_select($qa_name, $qa_value, $list)
+{
+    print "<select name=\"$qa_name\">\n";
+    if (empty($qa_value)) { $qa_value = ''; }
+    for($i = 0; $i < count($list); ++$i) {
+        print_select_item($list[$i], $list[$i], $qa_value);
+    }
+    print "</select>\n";
+}
+
 function print_qa_select_ext($qa_name, $qa_value = 0, $readonly = 1)
 {
     $state = '';
@@ -4079,6 +4089,7 @@ function update_record($db, $table, $filter, $newvalue)
     $run_sql = '';
     $network_changed = 0;
     $dhcp_changed = 0;
+    $dns_changed = 0;
 
     $acl_fields = [
         'ip' => '1',
@@ -4099,6 +4110,11 @@ function update_record($db, $table, $filter, $newvalue)
         'deleted' => '1',
         'mac' => '1',
     ];
+    
+    $dns_fields = [
+//        'dhcp_hostname' => '1',
+        'dns_name' => '1',
+    ];
 
     foreach ($newvalue as $key => $value) {
         if (!isset($value)) {
@@ -4115,6 +4131,9 @@ function update_record($db, $table, $filter, $newvalue)
             if (!empty($dhcp_fields["$key"])) {
                 $dhcp_changed = 1;
             }
+            if (!empty($dns_fields["$key"])) {
+                $dns_changed = 1;
+            }
         }
         if (!preg_match('/password/i',$key)) {
             $changed_log = $changed_log . " $key => $value (old: $old[$key]),";
@@ -4133,6 +4152,10 @@ function update_record($db, $table, $filter, $newvalue)
         $run_sql = $run_sql . " `dhcp_changed`='1',";
     }
 
+    if ($dns_changed) {
+        $run_sql = $run_sql . " `dns_changed`='1',";
+    }
+
     $changed_log = substr_replace($changed_log, "", -1);
     $run_sql = substr_replace($run_sql, "", -1);
 
@@ -4688,6 +4711,9 @@ if (preg_match('/127.0.0.1/', $config["torrus_url"])) {
     $config["torrus_url"] = NULL;
 }
 
+$config["dns_server"]=get_option($db_link,3);
+$config["dns_server_type"]=get_option($db_link,70);
+
 $ou = get_record_sql($db_link, "SELECT id FROM OU WHERE default_users = 1");
 if (empty($ou)) {
     $config["default_user_ou_id"] = 0;

+ 1 - 1
scripts/dhcp-log.pl

@@ -325,7 +325,7 @@ if (!$pid) {
             log_debug("SWITCH PORT:".$switch_port->{'ifName'}) if ($switch_port);
             log_debug("END GET");
 
-            update_dns_record($hdb,$dhcp_record,$auth_record);
+            update_dns_record_by_dhcp($hdb,$dhcp_record,$auth_record);
 
             if ($type=~/add/i and $dhcp_record->{hostname_utf8} and $dhcp_record->{hostname_utf8} !~/UNDEFINED/i) {
                 my $auth_rec;

+ 143 - 36
scripts/eyelib/mysql.pm

@@ -61,8 +61,9 @@ new_auth
 StrToIp
 get_first_line
 update_dns_record
-update_ad_hostname
-update_ad_ptr
+update_dns_record_by_dhcp
+update_dns_hostname
+update_dns_ptr
 update_record
 write_db_log
 set_changed
@@ -208,12 +209,15 @@ return if (!$db);
 return if (!$msg);
 $msg=~s/[\'\"]//g;
 my $db_log = 0;
-my $history_sql="INSERT INTO syslog(customer,message,level,auth_id) VALUES(".$db->quote($MY_NAME).",".$db->quote($msg).",$level,$auth_id)";
+if (!$db) { $db_log = 0; }
+
 if ($level eq $L_ERROR and $log_level >= $L_ERROR) { log_error($msg); $db_log = 1; }
 if ($level eq $L_WARNING and $log_level >= $L_WARNING) { log_warning($msg); $db_log = 1; }
 if ($level eq $L_INFO and $log_level >= $L_INFO) { log_info($msg); $db_log = 1; }
 if ($level eq $L_DEBUG and $log_level >= $L_DEBUG) { log_debug($msg); $db_log = 1; }
+
 if ($db_log) {
+    my $history_sql="INSERT INTO syslog(customer,message,level,auth_id) VALUES(".$db->quote($MY_NAME).",".$db->quote($msg).",$level,$auth_id)";
     my $history_rf=$db->prepare($history_sql) or die "Unable to prepare $history_sql:" . $db->errstr;
     $history_rf->execute() or die "Unable to execute $history_sql: " . $db->errstr;
     }
@@ -622,6 +626,74 @@ update_record($db,'User_auth',$update_record,"id=$id");
 
 sub update_dns_record {
 
+my $hdb = shift;
+my $auth_record = shift;
+
+if (!$auth_record->{dns_name}) { return 0; }
+
+my $ad_zone = get_option($hdb,33);
+
+#update dns block
+my $fqdn_static=lc($auth_record->{dns_name});
+$fqdn_static=~s/\.$ad_zone$//i;
+$fqdn_static=~s/\.$//;
+
+#skip update unknown domain
+if ($fqdn_static =~/\./) { return 0; }
+
+my $ad_dns = get_option($hdb,3);
+
+my $enable_ad_dns_update = ($ad_zone and $ad_dns and $config_ref{enable_dns_updates});
+
+log_debug("Auth record: ".Dumper($auth_record));
+log_debug("enable_ad_dns_update: ".$enable_ad_dns_update);
+log_debug("DNS update flags - zone: ".$ad_zone.", dns: ".$ad_dns.", enable_ad_dns_update: ".$enable_ad_dns_update);
+
+my $maybe_update_dns=( $enable_ad_dns_update and $office_networks->match_string($auth_record->{ip}) );
+if (!$maybe_update_dns) {
+    db_log_debug($hdb,"FOUND Auth_id: $auth_record->{id}. DNS update don't needed.");
+    return 0;
+    }
+
+log_debug("DNS update enabled.");
+
+$fqdn_static=lc($fqdn_static.'.'.$ad_zone);
+
+db_log_info($hdb,"Update dns request for auth_id: $auth_record->{id} $fqdn_static => $auth_record->{ip}");
+
+#check exists static dns name
+my $static_exists = 0;
+my $static_ok = 0;
+my $static_ref = '';
+
+my @dns_record=ResolveNames($fqdn_static,$dns_server);
+$static_exists = (scalar @dns_record>0);
+if ($static_exists) {
+        $static_ref = join(' ',@dns_record);
+        foreach my $dns_a (@dns_record) {
+            if ($dns_a=~/^$auth_record->{ip}$/) { $static_ok = 1; }
+            }
+        }
+
+db_log_debug($hdb,"Dns record for static record $fqdn_static: $static_ok");
+
+if (!$static_ok) {
+        if (!$static_exists) {
+                db_log_info($hdb,"Static dns hostname defined but not found. Create it ($fqdn_static => $auth_record->{ip})!");
+                } else {
+                db_log_warning($hdb,"Static record mismatch! Expected $fqdn_static => $auth_record->{ip}, recivied: $static_ref");
+                }
+        update_dns_hostname($fqdn_static,$auth_record->{ip},$ad_zone,$ad_dns,$hdb);
+        update_dns_ptr($fqdn_static,$auth_record->{ip},$ad_zone,$ad_dns,$hdb);
+        } else {
+	db_log_debug($hdb,"Static record for $fqdn_static [$static_ok] correct.");
+        }
+}
+
+#---------------------------------------------------------------------------------------------------------------
+
+sub update_dns_record_by_dhcp {
+
 my $hdb = shift;
 my $dhcp_record = shift;
 my $auth_record = shift;
@@ -701,7 +773,7 @@ if ($fqdn_static ne '') {
         db_log_info($hdb,"Static record mismatch! Expected $fqdn_static => $dhcp_record->{ip}, recivied: $static_ref");
         if (!$static_exists) {
                 db_log_info($hdb,"Static dns hostname defined but not found. Create it ($fqdn_static => $dhcp_record->{ip})!");
-                update_ad_hostname($fqdn_static,$dhcp_record->{ip},$ad_zone,$ad_dns,$hdb);
+                update_dns_hostname($fqdn_static,$dhcp_record->{ip},$ad_zone,$ad_dns,$hdb);
                 }
         } else {
 	db_log_debug($hdb,"Static record for $fqdn_static [$static_ok] correct.");
@@ -730,11 +802,11 @@ if ($fqdn ne '' and !$dynamic_ok) {
             if ($fqdn_static and $fqdn_static ne '') {
                     if ($fqdn_static!~/$fqdn/) {
                         db_log_info($hdb,"Hostname from dhcp request $fqdn differs from static dns hostanme $fqdn_static. Ignore dynamic binding!");
-#                        update_ad_hostname($fqdn,$dhcp_record->{ip},$ad_zone,$ad_dns,$hdb);
+#                        update_dns_hostname($fqdn,$dhcp_record->{ip},$ad_zone,$ad_dns,$hdb);
                         }
                     } else {
         	    db_log_info($hdb,"Static dns hostname not defined. Create dns record by dhcp request. $fqdn => $dhcp_record->{ip}");
-        	    update_ad_hostname($fqdn,$dhcp_record->{ip},$ad_zone,$ad_dns,$hdb);
+        	    update_dns_hostname($fqdn,$dhcp_record->{ip},$ad_zone,$ad_dns,$hdb);
         	    }
 	    } else {
             db_log_error($hdb,"Found another record with some hostname id: $name_record->{id} ip: $name_record->{ip} hostname: $name_record->{dns_name}. Skip update.");
@@ -789,40 +861,57 @@ sub unset_lock_discovery {
 
 #------------------------------------------------------------------------------------------------------------
 
-sub update_ad_hostname {
+sub update_dns_hostname {
 my $fqdn = shift;
 my $ip = shift;
 my $zone = shift;
 my $server = shift;
 my $db = shift;
-if (!$db) { 
+#skip update domain controllers
+if ($fqdn=~/^dc[0-9]{1,2}\./i) { return; }
+if (!$db) {
     log_info("DNS-UPDATE: Zone $zone Server: $server A: $fqdn IP: $ip"); 
     } else {
     db_log_info($db,"DNS-UPDATE: Zone $zone Server: $server A: $fqdn IP: $ip");
     }
 my $ad_zone = get_option($db,33);
-my @add_dns=();
-push(@add_dns,"gsstsig");
-push(@add_dns,"server $server");
-push(@add_dns,"zone $zone");
-push(@add_dns,"update delete $fqdn A");
-push(@add_dns,"update add $fqdn 3600 A $ip");
-push(@add_dns,"send");
-my $nsupdate_file = "/tmp/".$fqdn.".nsupdate";
-write_to_file($nsupdate_file,\@add_dns);
-do_exec('/usr/bin/kinit -k -t /opt/Eye/scripts/cfg/dns_updater.keytab dns_updater@'.uc($ad_zone).' && /usr/bin/nsupdate "'.$nsupdate_file.'"');
+my $nsupdate_file = "/tmp/".$fqdn."-nsupdate";
+my @add_dns;
+if ($config_ref{dns_server_type}=~/windows/i) {
+    push(@add_dns,"gsstsig");
+    push(@add_dns,"server $server");
+    push(@add_dns,"zone $zone");
+    push(@add_dns,"update delete $fqdn A");
+    push(@add_dns,"update add $fqdn 3600 A $ip");
+    push(@add_dns,"send");
+    write_to_file($nsupdate_file,\@add_dns);
+    do_exec('/usr/bin/kinit -k -t /opt/Eye/scripts/cfg/dns_updater.keytab dns_updater@'.uc($ad_zone).' && /usr/bin/nsupdate "'.$nsupdate_file.'"');
+    }
+
+if ($config_ref{dns_server_type}=~/bind/i) {
+    push(@add_dns,"server $server");
+    push(@add_dns,"zone $zone");
+    push(@add_dns,"update delete $fqdn A");
+    push(@add_dns,"update add $fqdn 3600 A $ip");
+    push(@add_dns,"send");
+    write_to_file($nsupdate_file,\@add_dns);
+    do_exec('/usr/bin/nsupdate -k /etc/bind/rndc.key "'.$nsupdate_file.'"');
+    }
+
 if (-e "$nsupdate_file") { unlink "$nsupdate_file"; }
 }
 
 #---------------------------------------------------------------------------------------------------------------
 
-sub update_ad_ptr {
+sub update_dns_ptr {
 my $fqdn = shift;
 my $ip = shift;
 my $server = shift;
 my $db = shift;
 my $radr;
 my $zone;
+#skip update domain controllers
+if ($fqdn=~/^dc[0-9]{1,2}\./i) { return; }
 if ($ip =~ /([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})(\/[0-9]{1,2}){0,1}/) {
     return 0 if($1 > 255 || $2 > 255 || $3 > 255 || $4 > 255);
     $radr = "$4.$3.$2.$1.in-addr.arpa";
@@ -835,17 +924,31 @@ if (!$db) {
     db_log_info($db,"DNS-UPDATE: Zone $zone Server: $server A: $fqdn PTR: $ip");
     }
 my $ad_zone = get_option($db,33);
-my @add_dns=();
-push(@add_dns,"gsstsig");
-push(@add_dns,"server $server");
-push(@add_dns,"zone $zone");
-push(@add_dns,"update delete $radr PTR");
-push(@add_dns,"update add $radr 3600 PTR $fqdn.");
-push(@add_dns,"send");
-my $nsupdate_file = "/tmp/".$radr.".nsupdate";
-write_to_file($nsupdate_file,\@add_dns);
-my $run_cmd = '/usr/bin/kinit -k -t /opt/Eye/scripts/cfg/dns_updater.keytab dns_updater@'.uc($ad_zone).' && /usr/bin/nsupdate "'.$nsupdate_file.'"';
-do_exec($run_cmd);
+my $nsupdate_file = "/tmp/".$radr."-nsupdate";
+my @add_dns;
+if ($config_ref{dns_server_type}=~/windows/i) {
+    push(@add_dns,"gsstsig");
+    push(@add_dns,"server $server");
+    push(@add_dns,"zone $zone");
+    push(@add_dns,"update delete $radr PTR");
+    push(@add_dns,"update add $radr 3600 PTR $fqdn.");
+    push(@add_dns,"send");
+    write_to_file($nsupdate_file,\@add_dns);
+    my $run_cmd = '/usr/bin/kinit -k -t /opt/Eye/scripts/cfg/dns_updater.keytab dns_updater@'.uc($ad_zone).' && /usr/bin/nsupdate "'.$nsupdate_file.'"';
+    do_exec($run_cmd);
+    }
+
+if ($config_ref{dns_server_type}=~/bind/i) {
+    push(@add_dns,"server $server");
+    push(@add_dns,"zone $zone");
+    push(@add_dns,"update delete $radr PTR");
+    push(@add_dns,"update add $radr 3600 PTR $fqdn.");
+    push(@add_dns,"send");
+    write_to_file($nsupdate_file,\@add_dns);
+    my $run_cmd = '/usr/bin/nsupdate -k /etc/bind/rndc.key "'.$nsupdate_file.'"';
+    do_exec($run_cmd);
+    }
+
 if (-e "$nsupdate_file") { unlink "$nsupdate_file"; }
 }
 
@@ -1081,11 +1184,9 @@ my $default_option = get_record_sql($db,'SELECT * FROM config_options WHERE id='
 my $config_options = get_record_sql($db,'SELECT * FROM config WHERE option_id='.$option_id);
 my $result;
 if (!$config_options) {
-    if ($default_option->{'type'}=~/int/i or $default_option->{'type'}=~/bool/i) {
-	$result = $default_option->{'default_value'}*1;
-	} else {
-	$result = $default_option->{'default_value'};
-	}
+    if ($default_option->{'type'}=~/^(int|bool)/i) { $result = $default_option->{'default_value'}*1; };
+    if ($default_option->{'type'}=~/^(string|text)/i) { $result = $default_option->{'default_value'}; }
+    if ($default_option->{'type'}=~/^list/i) { $result = $default_option->{'default_value'}; }
     return $result;
     }
 $result = $config_options->{'value'};
@@ -1102,7 +1203,6 @@ $last_refresh_config = time();
 $config_ref{dbh}=$db;
 $config_ref{save_detail}=get_option($db,23);
 $config_ref{add_unknown_user}=get_option($db,22);
-$config_ref{dns_server}=get_option($db,3);
 $config_ref{dhcp_server}=get_option($db,5);
 $config_ref{snmp_default_version}=get_option($db,9);
 $config_ref{snmp_default_community}=get_option($db,11);
@@ -1144,11 +1244,18 @@ $config_ref{stat_url} = get_option($db,62);
 $config_ref{wiki_path} = get_option($db,61);
 
 $config_ref{auto_mac_rule} = get_option($db,64);
+
 #network configuration mode
 $config_ref{config_mode}=get_option($db,68);
+
 #auto clean old user record
 $config_ref{clean_empty_user}=get_option($db,69);
 
+#dns_server_type
+$config_ref{dns_server}=get_option($db,3);
+$config_ref{dns_server_type}=get_option($db,70);
+$config_ref{enable_dns_updates}=get_option($db,71);
+
 #$save_detail = 1; id=23
 $save_detail=get_option($db,23);
 #$add_unknown_user = 1; id=22

+ 35 - 23
scripts/stat-sync.pl

@@ -88,34 +88,46 @@ if (!$pid) {
         if ( !defined $hdb ) { die "Cannot connect to mySQL server: $DBI::errstr\n"; }
         $urgent_sync=get_option($hdb,50);
         if ($urgent_sync) {
-    	    #clean changed for dynamic clients or hotspot
-    	    do_sql($hdb,"UPDATE User_auth SET changed=0 WHERE ou_id=".$default_user_ou_id." OR ou_id=".$default_hotspot_ou_id);
-    	    do_sql($hdb,"UPDATE User_auth SET dhcp_changed=0 WHERE ou_id=".$default_user_ou_id." OR ou_id=".$default_hotspot_ou_id);
-    	    #clean unmanagment ip changed
-    	    my @all_changed = get_records_sql($hdb,"SELECT id, ip FROM User_auth WHERE changed = 1 OR dhcp_changed = 1");
-    	    foreach my $row(@all_changed) {
-    		    next if ($office_networks->match_string($row->{ip}));
-    		    do_sql($hdb,"UPDATE User_auth SET changed = 0, dhcp_changed = 0 WHERE id=".$row->{id});
-    		    }
+	    #clean changed for dynamic clients or hotspot
+	    do_sql($hdb,"UPDATE User_auth SET changed=0 WHERE ou_id=".$default_user_ou_id." OR ou_id=".$default_hotspot_ou_id);
+	    do_sql($hdb,"UPDATE User_auth SET dhcp_changed=0 WHERE ou_id=".$default_user_ou_id." OR ou_id=".$default_hotspot_ou_id);
+	    do_sql($hdb,"UPDATE User_auth SET dns_changed=0 WHERE ou_id=".$default_user_ou_id." OR ou_id=".$default_hotspot_ou_id);
+	    #clean unmanagment ip changed
+	    my @all_changed = get_records_sql($hdb,"SELECT id, ip FROM User_auth WHERE changed = 1 OR dhcp_changed = 1 OR dns_changed = 1");
+	    foreach my $row(@all_changed) {
+		    next if ($office_networks->match_string($row->{ip}));
+		    do_sql($hdb,"UPDATE User_auth SET changed = 0, dhcp_changed = 0, dns_changed = 0  WHERE id=".$row->{id});
+		}
             #dhcp changed records
             my $changed = get_record_sql($hdb,"SELECT COUNT(*) as c_count from User_auth WHERE dhcp_changed=1");
-	        if ($changed->{"c_count"}>0) {
+            if ($changed->{"c_count"}>0) {
         	    do_sql($hdb,"UPDATE User_auth SET dhcp_changed=0");
-                log_info("Found changed dhcp variables in records: ".$changed->{'c_count'});
-                my $dhcp_exec=get_option($hdb,38);
-    	        my %result=do_exec_ref($dhcp_exec);
-    	        if ($result{status} ne 0) { log_error("Error sync dhcp config"); }
-    	    	}
+                    log_info("Found changed dhcp variables in records: ".$changed->{'c_count'});
+                    my $dhcp_exec=get_option($hdb,38);
+	            my %result=do_exec_ref($dhcp_exec);
+	            if ($result{status} ne 0) { log_error("Error sync dhcp config"); }
+	        }
+
+            #dns changed records
+            my @dns_changed = get_records_sql($hdb,"SELECT id,dns_name,ip from User_auth WHERE deleted=0 AND dns_changed=1");
+            if (@dns_changed and scalar @dns_changed) {
+                    foreach my $auth (@dns_changed) {
+                        update_dns_record($hdb,$auth);
+        	        do_sql($hdb,"UPDATE User_auth SET dns_changed=0 WHERE id=".$auth->{id});
+                        log_info("Clear changed dns for auth id: ".$auth->{id});
+                    }
+	        }
+
             #acl & dhcp changed records 
             $changed = get_record_sql($hdb,"SELECT COUNT(*) as c_count from User_auth WHERE changed=1");
-	        if ($changed->{"c_count"}>0) {
-                log_info("Found changed records: ".$changed->{'c_count'});
-                my $acl_exec=get_option($hdb,37);
-    	        my %result=do_exec_ref($acl_exec);
-    	        if ($result{status} ne 0) { log_error("Error sync status at gateways"); }
-    	    	}
-    	    }
-    	sleep(60);
+	    if ($changed->{"c_count"}>0) {
+                    log_info("Found changed records: ".$changed->{'c_count'});
+                    my $acl_exec=get_option($hdb,37);
+                    my %result=do_exec_ref($acl_exec);
+	            if ($result{status} ne 0) { log_error("Error sync status at gateways"); }
+		}
+	    }
+	sleep(60);
         };
         if ($@) { log_error("Exception found: $@"); sleep(300); }
         }

+ 3 - 1
updates/2-4-14/options.sql

@@ -1,4 +1,6 @@
 INSERT INTO `config_options` (`id`, `option_name`, `description.russian`, `description.english`, `uniq`, `type`, `default_value`, `min_value`, `max_value`) VALUES ('69', 'clean_empty_user', 'Автоматически удалять записи пользователей, не содержащие ip-адресов или автоматических привязок', 'Automatically delete user records that do not contain IP addresses or automatic bindings', '1', 'bool', '0', '0', '1');
 UPDATE `config_options` SET `min_value` = '0' WHERE `config_options`.`min_value`<>0 AND `config_options`.`type`='bool';
 UPDATE `config_options` SET `max_value` = '1' WHERE `config_options`.`max_value`<>1 AND `config_options`.`type`='bool';
-
+ALTER TABLE `config_options` CHANGE `type` `type` VARCHAR(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL;
+INSERT INTO `config_options` (`id`, `option_name`, `description.russian`, `description.english`, `uniq`, `type`, `default_value`, `min_value`, `max_value`) VALUES ('70', 'dns_server_type', 'Тип используемого dns-сервера: Windows, Bind. Если используется локальный dnsmasq - параметры dns-сервера указывать не надо.', 'The type of dns server used: Windows, Bind. If you are using a local dnsmasq, you do not need to specify the dns server parameters.', '1', 'list;windows;bind', 'bind', '0', '0');
+INSERT INTO `config_options` (`id`, `option_name`, `description.russian`, `description.english`, `uniq`, `type`, `default_value`, `min_value`, `max_value`) VALUES ('71', 'enable_dns_updates', 'Включить обновления DNS имен при изменении dns-имени в ip-записи', 'Enable DNS name updates when dns name changes in an ip record', '1', 'bool', '0', '0', '1');

+ 3 - 0
updates/2-4-14/user_auth.sql

@@ -0,0 +1,3 @@
+ALTER TABLE `User_auth` ADD `dns_changed` INT NOT NULL DEFAULT '0' AFTER `dhcp_changed`;
+ALTER TABLE `User_auth` CHANGE `dhcp_changed` `dhcp_changed` INT(11) NOT NULL DEFAULT '0';
+ALTER TABLE `User_auth_alias` ADD `changed` INT NOT NULL DEFAULT '0' AFTER `timestamp`;