Przeglądaj źródła

added config for use php-fpm
rewrite provisiong module for switch access
bugfix: fixed path for pid file

root 1 rok temu
rodzic
commit
ba8c7e4

+ 3 - 1
Readme.en.md

@@ -17,7 +17,7 @@ apt install perl libnet-patricia-perl libnetaddr-ip-perl libconfig-tiny-perl lib
 libnet-netmask-perl libtext-iconv-perl libnet-snmp-perl libnet-telnet-perl libdbi-perl \
 libdbd-mysql-perl libparallel-forkmanager-perl libproc-daemon-perl libdatetime-format-dateparse-perl \
 libnetwork-ipv4addr-perl libnet-openssh-perl libfile-tail-perl  \
-libcrypt-cbc-perl libcryptx-perl libdbd-pg-perl libfile-path-tiny-perl
+libcrypt-cbc-perl libcryptx-perl libdbd-pg-perl libfile-path-tiny-perl libexpect-perl
 
 #additional packages 
 apt install dnsmasq syslong-ng bind9 bind9-utils bind9-host
@@ -28,6 +28,8 @@ addgroup --system eye
 adduser --system  --disabled-password --disabled-login --ingroup eye --home=/opt/Eye eye
 chmod 770 /opt/Eye
 
+2.1 For nagios
+usermod -a -G eye nagios
 
 3. Download the source code and spread it in catalogs:
 

+ 27 - 15
Readme.ru.md

@@ -2,27 +2,36 @@
 
 1. Ставим пакеты
 
-#common
+#общая часть
 apt install git xxd bsdmainutils
 
-#for database server
+#для сервера с БД
 apt install mariadb-server
 
-#for web
+#для сервера с вэбом
 apt install apache2 libapache2-mod-fcgid \
 php php-mysql php-bcmath php-intl php-mbstring php-date php-mail php-snmp php-zip php-fpm php-db php-pgsql
 
-#for backend
+#для ядра
 apt install perl libnet-patricia-perl libnetaddr-ip-perl libconfig-tiny-perl libnet-dns-perl libdatetime-perl \
 libnet-netmask-perl libtext-iconv-perl libnet-snmp-perl libnet-telnet-perl libdbi-perl \
 libdbd-mysql-perl libparallel-forkmanager-perl libproc-daemon-perl libdatetime-format-dateparse-perl \
 libnetwork-ipv4addr-perl libnet-openssh-perl libfile-tail-perl  \
-libcrypt-cbc-perl libcryptx-perl libdbd-pg-perl libfile-path-tiny-perl
+libcrypt-cbc-perl libcryptx-perl libdbd-pg-perl libfile-path-tiny-perl libexpect-perl
 
-#additional packages
+#дополнительно
 apt install dnsmasq syslong-ng bind9 bind9-utils bind9-host
 
-2. Качаем исходники и раскидываем по каталогам:
+2. Create user and group
+
+addgroup --system eye
+adduser --system  --disabled-password --disabled-login --ingroup eye --home=/opt/Eye eye
+chmod 770 /opt/Eye
+
+2.1 Если нужна работа с nagios
+usermod -a -G eye nagios
+
+3. Качаем исходники и раскидываем по каталогам:
 
 git clone https://github.com/rajven/Eye
 mkdir -p /opt/Eye/scripts
@@ -32,7 +41,7 @@ cd Eye/
 cp -R scripts/ /opt/Eye/
 cp -R html/ /opt/Eye/
 
-3. Можно скачать дополнительные скрипты (красивости)
+4. Можно скачать дополнительные скрипты (красивости)
 
 mkdir -p /opt/Eye/html/js/jq
 mkdir -p /opt/Eye/html/js/select2
@@ -54,7 +63,7 @@ download jstree from  https://github.com/vakata/jstree/
 #rm -d /opt/Eye/html/vakata-jstree-7a03954
 #rm -f js.zip
 
-4. Настраиваем mysql 
+5. Настраиваем mysql 
 
 systemctl enable mariadb
 systemctl start mariadb
@@ -74,7 +83,7 @@ quit
 Импортировать дефалтные таблицы
 cat docs/mysql/mysql.sql | mysql -u root -p stat
 
-5. Настраиваем конфиги для вэба и скриптов:
+6. Настраиваем конфиги для вэба и скриптов:
 
 cp html/inc/config.sample.php /opt/Eye/html/cfg/
 mv /opt/Eye/html/cfg/config.sample.php /opt/Eye/html/cfg/config.php
@@ -91,7 +100,7 @@ edit: /opt/Eye/scripts/cfg/config
 Пароль: pwgen 16
 Вектор: tr -dc 0-9 </dev/urandom | head -c 16 ; echo ''
 
-6. Настраиваем апач и php:
+7. Настраиваем апач и php:
 
 sed -i 's/short_open_tag = Off/short_open_tag = On/' /etc/php/7.4/apache2/php.ini
 sed -i 's/;date.timezone =/date.timezone = Europe\/Moscow/' /etc/php/7.4/apache2/php.ini
@@ -102,7 +111,7 @@ systemctl start apache2
 
 cp docs/sudoers.d/www-data /etc/sudoers.d/www-data
 
-7. Cron & logrotate
+8. Cron & logrotate
 
 cp docs/cron/stat /etc/cron.d/stat
 cp docs/logrotate/dnsmasq /etc/logrotate.d/dnsmasq
@@ -110,9 +119,9 @@ cp docs/logrotate/scripts /etc/logrotate.d/scripts
 
 Не забудьте раскомментировать в кроне неоходимые скрипты
 
-8. Минимальная настройка готова! Заходим: http://[ip]/admin/ user: admin password: admin, настраиваем список устройств, используемые сети и т.д.
+9. Минимальная настройка готова! Заходим: http://[ip]/admin/ user: admin password: admin, настраиваем список устройств, используемые сети и т.д.
 
-9. Change admin password and api key!!!
+10. Change admin password and api key!!!
 
 ######################################### DHCP Server at Linux ###############################################################
 
@@ -147,8 +156,11 @@ systemctl enable stat-sync.service
 ######################################### Network flow #####################################################################
 
 Включаем netflow на роутере микротик:
-/ip traffic-flow
+#for ROS 6
 set enabled=yes
+#for ROS 7
+set enabled=yes  interfaces=WAN
+
 /ip traffic-flow target
 add dst-address=[IP-SERVER] port=2055
 

+ 62 - 10
docs/apache/000-default.conf

@@ -1,19 +1,71 @@
 <VirtualHost *:80>
 
-	#ServerName www.example.com
+#ServerName www.example.com
 
-	ServerAdmin webmaster@localhost
+ServerAdmin webmaster@localhost
 
-	DocumentRoot /opt/Eye/html
+ErrorLog ${APACHE_LOG_DIR}/stat-error_log
+TransferLog ${APACHE_LOG_DIR}/stat-access_log
 
-	<Directory /opt/Eye/html/>
-	    Options Indexes FollowSymLinks
-	    AllowOverride None
-	    Require all granted
-	</Directory>
+#don't enable redirect to HTTPS!!!
+RewriteEngine Off
 
-	ErrorLog ${APACHE_LOG_DIR}/error.log
-	CustomLog ${APACHE_LOG_DIR}/access.log combined
+DocumentRoot /opt/Eye/html
+
+<Directory "/opt/Eye/html">
+    Options -Indexes -FollowSymLinks
+    AllowOverride All
+    Require all granted
+
+    AddType application/x-httpd-php .php
+
+# Redirect to local php-fpm if mod_php is not available
+<IfModule !mod_php8.c>
+<IfModule proxy_fcgi_module>
+    # Enable http authorization headers
+    <IfModule setenvif_module>
+    SetEnvIfNoCase ^Authorization$ "(.+)" HTTP_AUTHORIZATION=$1
+    </IfModule>
+
+    <FilesMatch ".+\.ph(ar|p|tml)$">
+#    SetHandler "proxy:unix:/run/php/php8.1-fpm-eye.sock|fcgi://127.0.0.1:9002"
+    SetHandler "proxy:fcgi://127.0.0.1:9002"
+    </FilesMatch>
+
+    <FilesMatch ".+\.phps$">
+        # Deny access to raw php sources by default
+        # To re-enable it's recommended to enable access to the files
+        # only in specific virtual host or directory
+        Require all denied
+    </FilesMatch>
+    # Deny access to files without filename (e.g. '.php')
+    <FilesMatch "^\.ph(ar|p|ps|tml)$">
+        Require all denied
+    </FilesMatch>
+</IfModule>
+</IfModule>
+
+</Directory>
+
+<Directory /opt/Eye/html/log>
+    <IfModule mod_authz_core.c>
+    Require all denied
+    </IfModule>
+</Directory>
+
+<Directory /opt/Eye/html/tmp>
+    <IfModule mod_authz_core.c>
+    Require all denied
+    </IfModule>
+</Directory>
+
+<Directory /opt/Eye/html/session>
+    <IfModule mod_authz_core.c>
+    Require all denied
+    </IfModule>
+</Directory>
+
+AddDefaultCharset UTF-8
 
 </VirtualHost>
 

+ 14 - 0
docs/apache/cron.d/php-fpm

@@ -0,0 +1,14 @@
+# /etc/cron.d/php@PHP_VERSION@: crontab fragment for PHP
+#  This purges session files in session.save_path older than X,
+#  where X is defined in seconds as the largest value of
+#  session.gc_maxlifetime from all your SAPI php.ini files
+#  or 24 minutes if not defined.  The script triggers only
+#  when session.save_handler=files.
+#
+#  WARNING: The scripts tries hard to honour all relevant
+#  session PHP options, but if you do something unusual
+#  you have to disable this script and take care of your
+#  sessions yourself.
+
+# Look for and purge old sessions every 30 minutes
+09,39 *     * * *     root   [ -x /usr/lib/php/sessionclean-fpm ] && if [ ! -d /run/systemd/system ]; then /usr/lib/php/sessionclean-fpm; fi

+ 65 - 0
docs/apache/php-fpm/eye.conf

@@ -0,0 +1,65 @@
+[eye]
+user = eye
+group = eye
+
+listen = 127.0.0.1:9002
+listen.allowed_clients = 127.0.0.1
+
+;listen = /run/php/php8.1-fpm-eye.sock
+;listen.owner = www-data
+;listen.group = www-data
+
+pm = dynamic
+pm.max_children = 10
+pm.start_servers = 5
+pm.min_spare_servers = 1
+pm.max_spare_servers = 5
+
+access.log = /var/log/php-fpm/fpm-$pool.access.log
+access.format = "%{REMOTE_ADDR}e - %u %t \"%m %r%Q%q\" %s %f %{milli}d %{kilo}M %C%%"
+
+;slowlog = /opt/Eye/html/log/$pool.slow.log
+;request_slowlog_timeout = 0
+
+security.limit_extensions = .php
+
+;clear_env = no
+
+env[HOSTNAME] = $HOSTNAME
+env[PATH] = /usr/bin:/bin
+
+env[TMP] = /opt/Eye/html/tmp
+env[TMPDIR] = /opt/Eye/html/tmp
+env[TEMP] = /opt/Eye/html/tmp
+
+php_admin_value[sys_temp_dir] = /opt/Eye/html/tmp
+php_admin_value[upload_tmp_dir] = /opt/Eye/html/tmp
+php_admin_value[open_basedir]= /opt/Eye/html/:/opt/Eye/html/tmp:/opt/Eye/html/sessions
+
+php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f no-reply@oem.ru
+
+php_admin_value[short_open_tag] = On
+php_admin_value[session.save_path] = /opt/Eye/html/sessions
+
+php_admin_value[display_errors] = Off
+php_admin_value[error_log] = /opt/Eye/html/log/fpm-php.error.log
+php_admin_value[log_errors] = on
+
+php_admin_value[mbstring.default_charset] = UTF-8
+php_admin_value[mbstring.internal_encoding] = UTF-8
+php_admin_value[mbstring.detect_order] = "UTF-8"
+php_admin_value[mbstring.encoding_translation] = on
+php_admin_value[mbstring.func_overload] = 2
+php_admin_value[mbstring.internal_encoding] = UTF-8
+
+php_admin_value[file_uploads] = Off
+php_admin_value[post_max_size] = 10M
+
+php_admin_value[memory_limit] = 128M
+
+php_admin_value[allow_url_fopen] = Off
+php_admin_value[mail.add_x_header] = Off
+
+php_admin_value[opcache.revalidate_freq] = 0
+
+php_admin_value[date.timezone] = Europe/Moscow

+ 6 - 4
docs/apache/php-fpm/readme.txt

@@ -1,16 +1,18 @@
-a2dismod php7.4
+a2dismod php8.1
 a2dismod mpm_prefork
 a2enmod mpm_event
 
 apt install php-fpm libapache2-mod-fcgid
 
-a2enconf php7.4-fpm
+a2enconf php8.1-fpm
 a2enmod proxy
 
+mkdir -p /var/log/php-fpm/
+
 apachectl configtest
 
-systemctl enable php7.4-fpm.service
-systemctl restart php7.4-fpm.service
+systemctl enable php8.1-fpm.service
+systemctl restart php8.1-fpm.service
 
 systemctl restart apache2
 

+ 77 - 0
docs/apache/sessionsclean-fpm

@@ -0,0 +1,77 @@
+#!/bin/sh -e
+#
+# sessionclean - a script to cleanup stale PHP sessions
+#
+# Copyright 2013-2015 Ondřej Surý <ondrej@sury.org>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy of
+# this software and associated documentation files (the "Software"), to deal in
+# the Software without restriction, including without limitation the rights to
+# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+# the Software, and to permit persons to whom the Software is furnished to do so,
+# subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+SAPIS="fpm:php-fpm@VERSION@"
+
+# Iterate through all web SAPIs
+(
+proc_names=""
+for version in $(/usr/sbin/phpquery -V); do
+    for sapi in ${SAPIS}; do
+        conf_dir=${sapi%%:*}
+        proc_name=${sapi##*:}
+        if [ -e "/etc/php/${version}/${conf_dir}/php.ini" ] && [ -x "/usr/bin/php${version}" ]; then
+            for pool in /etc/php/${version}/${conf_dir}/pool.d/*.conf; do
+                # Get all session variables once so we don't need to start PHP to get each config option
+                session_config=$(PHP_INI_SCAN_DIR=/etc/php/${version}/${conf_dir}/conf.d/ "/usr/bin/php${version}" -c "/etc/php/${version}/${conf_dir}/php.ini" -d "error_reporting='~E_ALL'" -r 'foreach(ini_get_all("session") as $k => $v) echo "$k=".$v["local_value"]."\n";')
+                #default session path
+                save_handler=$(echo "$session_config" | sed -ne 's/^session\.save_handler=\(.*\)$/\1/p')
+                save_path=$(echo "$session_config" | sed -ne 's/^session\.save_path=\(.*;\)\?\(.*\)$/\2/p')
+                gc_maxlifetime=$(($(echo "$session_config" | sed -ne 's/^session\.gc_maxlifetime=\(.*\)$/\1/p')/60))
+
+                sh_ok=$(grep "session\.save_handler" "${pool}" | egrep -v "^[;#]" )
+                sp_ok=$(grep "session\.save_path" "${pool}" | egrep -v "^[;#]")
+                sg_ok=$(grep "session\.gc_maxlifetime" "${pool}" | egrep -v "^[;#]")
+
+                if [ -n "${sh_ok}" ]; then
+                        save_handler=$(grep "session\.save_handler" "${pool}" | egrep -v "^[;#]" | awk -F "=" '{ print $NF }' | sed 's/^\s*//g')
+                    fi
+                if [ -n "${sp_ok}" ]; then
+                        save_path=$(grep "session\.save_path" "${pool}" | egrep -v "^[;#]" | awk -F "=" '{ print $NF }' | sed 's/^\s*//g')
+                    fi
+
+                if [ -n "${sg_ok}" ]; then
+                        gc_maxlifetime=$(($(grep "session\.gc_maxlifetime" "${pool}" | egrep -v "^[;#]" | awk -F "=" '{ print $NF }' | sed 's/^\s*//g')/60))
+                    fi
+
+                if [ "$save_handler" = "files" ] && [ -d "$save_path" ]; then
+                        proc_names="$proc_names $(echo "$proc_name" | sed -e "s,@VERSION@,$version,")";
+                        printf "%s:%s\n" "$save_path" "$gc_maxlifetime"
+                fi
+            done
+        fi
+    done
+done
+# first find all open session files and touch them (hope it's not massive amount of files)
+for pid in $(pidof $proc_names); do
+    find "/proc/$pid/fd" -ignore_readdir_race -lname "$save_path/sess_*" -exec touch -c {} \; 2>/dev/null
+done ) | \
+    sort -rn -t: -k2,2 | \
+    sort -u -t: -k 1,1 | \
+    while IFS=: read -r save_path gc_maxlifetime; do
+        # find all files older then maxlifetime and delete them
+        [ -z "${save_path}" ] && continue
+        find -O3 "$save_path/" -ignore_readdir_race -depth -mindepth 1 -name 'sess_*' -type f -cmin "+$gc_maxlifetime" -delete
+    done
+
+exit 0

+ 101 - 105
scripts/eyelib/cmd.pm

@@ -17,6 +17,7 @@ use eyelib::config;
 use eyelib::main;
 use Net::Telnet;
 use Net::OpenSSH;
+use Expect;
 
 @ISA = qw(Exporter);
 @EXPORT = qw(
@@ -256,6 +257,7 @@ return 1;
 
 sub netdev_login {
 my $device = shift;
+
 #skip unknown vendor
 if (!$switch_auth{$device->{vendor_id}}) { return 0; }
 
@@ -292,39 +294,19 @@ if ($device->{proto} eq 'telnet') {
         if (exists $switch_auth{$device->{vendor_id}}{password}) { $t->waitfor("/$switch_auth{$device->{vendor_id}}{password}/"); }
         $t->print($device->{password});
         $t->waitfor("/$switch_auth{$device->{vendor_id}}{prompt}/");
-        if (exists $switch_auth{$device->{vendor_id}}{enable}) {
-            $t->print($switch_auth{$device->{vendor_id}}{enable});
-            $t->print($device->{enable_password}) if ($device->{enable_password});
-            $t->waitfor("/$switch_auth{$device->{vendor_id}}{prompt}/");
-            }
-        if ($device->{vendor_id} eq '2') {
-            log_cmd($t,"terminal datadump");
-            log_cmd($t,"no logging console");
-            }
-        if ($device->{vendor_id} eq '5') { log_cmd($t,"terminal page-break disable"); }
-        if ($device->{vendor_id} eq '6') { log_cmd($t,"terminal length 0"); }
-        if ($device->{vendor_id} eq '9') { log_cmd4($t,"/system note set show-at-login=no"); }
-        if ($device->{vendor_id} eq '16') { log_cmd($t,"terminal width 0"); }
-        if ($device->{vendor_id} eq '17') {
-            log_cmd($t,"more displine 50");
-            log_cmd($t,"more off");
-            }
-        if ($device->{vendor_id} eq '38') {
-            log_cmd($t,"disable cli prompting");
-            log_cmd($t,"disable clipaging");
-            }
         };
     if ($@) { log_error("Login to $device->{device_name} ip: $device->{ip} by telnet aborted: $@"); return 0; } else { log_info("Login to $device->{device_name} ip: $device->{ip} by telnet success!"); }
     }
 
 if ($device->{proto} eq 'ssh') {
     if (!$device->{port}) { $device->{port} = '22'; }
-    log_info("Try login to $device->{device_name} $device->{ip}:$device->{port} by ssh...");
+    log_info("Try login to $device->{device_name} $device->{ip}:$device->{port} by OpenSSH...");
 	$t = Net::OpenSSH->new($device->{ip},
 	    user=>$device->{login},
 	    password=>$device->{password},
 	    port=>$device->{port},
 	    timeout=>30,
+	    strict_mode=>0,
 	    master_opts => [ 
 	    -o => "StrictHostKeyChecking=no", 
 	    -o => "PubkeyAcceptedKeyTypes=+ssh-dss", 
@@ -336,36 +318,66 @@ if ($device->{proto} eq 'ssh') {
 	    );
 
         if ($t->error) {  log_error("Login to $device->{device_name} ip: $device->{ip} by ssh aborted: ".$t->error); return 0; }
+    }
 
-        netdev_set_enable($t,$device);
+if ($device->{proto} eq 'essh') {
+	if (!$device->{port}) { $device->{port} = '22'; }
+	log_info("Try login to $device->{device_name} $device->{ip}:$device->{port} by ssh::expect...");
 
-        if ($device->{vendor_id} eq '2') {
-            $t->capture("terminal datadump");
-            $t->capture("no logging console");
-            }
-        if ($device->{vendor_id} eq '5') {
-            $t->capture("terminal page-break disable");
-            }
-        if ($device->{vendor_id} eq '6') {
-            $t->capture("terminal length 0");
-            }
-#        if ($device->{vendor_id} eq '9') {
-#            $t->capture("/system note set show-at-login=no");
-#            }
-        if ($device->{vendor_id} eq '16') {
-            $t->capture("terminal width 0");
-            }
-        if ($device->{vendor_id} eq '17') {
-            $t->capture("more displine 50");
-            $t->capture("more off");
-            }
-        if ($device->{vendor_id} eq '38') {
-            $t->capture("disable cli prompting");
-            $t->capture("disable clipaging");
-            }
+	$t = Expect->spawn("ssh -o StrictHostKeyChecking=no -o PubkeyAcceptedKeyTypes=+ssh-dss -o KexAlgorithms=+diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1 -o HostKeyAlgorithms=+ssh-dss -o LogLevel=quiet -o UserKnownHostsFile=/dev/null $device->{login}\@$device->{ip}");
+	$t->log_stdout(0);  # Disable logging to stdout
+
+	$t->expect(30,
+	[ qr/(?i)password:/ => sub {
+    	    my $exp = shift;
+    	    $exp->send("$device->{password}\n");
+    	    exp_continue;
+	}],
+	[ qr/(?i)yes\/no/ => sub {
+        my $exp = shift;
+        $exp->send("yes\n");
+        exp_continue;
+	}]
+	);
+    }
+
+if ($t) {
     log_info("Login to $device->{device_name} ip: $device->{ip} by ssh success!");
+    } else {
+    log_error("Login to $device->{device_name} ip: $device->{ip} by ssh failed!");
+    return 0;
     }
 
+netdev_set_enable($t,$device);
+
+my @init_cmd=();
+
+if ($device->{vendor_id} eq '2') {
+        push(@init_cmd,"terminal datadump");
+        push(@init_cmd,"no logging console");
+        }
+if ($device->{vendor_id} eq '5') {
+        push(@init_cmd,"terminal page-break disable");
+        }
+if ($device->{vendor_id} eq '6') {
+        push(@init_cmd,"terminal length 0");
+        }
+if ($device->{vendor_id} eq '9') {
+        push(@init_cmd,"/system note set show-at-login=no");
+        }
+if ($device->{vendor_id} eq '16') {
+        push(@init_cmd,"terminal width 0");
+        }
+if ($device->{vendor_id} eq '17') {
+        push(@init_cmd,"more displine 50");
+        push(@init_cmd,"more off");
+        }
+if ($device->{vendor_id} eq '38') {
+        push(@init_cmd,"disable cli prompting");
+        push(@init_cmd,"disable clipaging");
+        }
+netdev_cmd($device,$t,\@init_cmd,3);
+
 return $t;
 }
 
@@ -376,18 +388,19 @@ my $session = shift;
 my $device = shift;
 return if (!exists $switch_auth{$device->{vendor_id}}{enable});
 my $cmd = $switch_auth{$device->{vendor_id}}{enable};
-netdev_cmd($device,$session,$device->{proto},$cmd,3);
-if ($device->{enable_password}) { netdev_cmd($device,$session,$device->{proto},$device->{enable_password},3); }
+netdev_cmd($device,$session,$cmd,3);
+if ($device->{enable_password}) { netdev_cmd($device,$session,$device->{enable_password},3); }
 }
 
 #---------------------------------------------------------------------------------
 
 sub netdev_cmd {
-my ($device,$session,$proto,$cmd,$telnet_version)=@_;
+my ($device,$session,$cmd,$telnet_version)=@_;
 my @result=();
 my @tmp=();
 if (ref($cmd) eq 'ARRAY') { @tmp = @{$cmd}; } else { @tmp = split(/\n/,$cmd); }
-if ($proto eq 'ssh') {
+
+if ($device->{proto} eq 'ssh') {
     eval {
     foreach my $run_cmd (@tmp) {
         next if (!$run_cmd);
@@ -396,57 +409,40 @@ if ($proto eq 'ssh') {
             next;
             }
         log_session('Send:'.$run_cmd);
-        my @row = $session->capture($run_cmd);
+        select(undef, undef, undef, 0.25);
+        my @row = $session->capture($run_cmd."\r\n");
 	chomp(@row);
         push(@result,@row);
-        select(undef, undef, undef, 0.25);
+#	my ($output, $errput) = $session->capture2({timeout => 5}, $run_cmd);
+#	$session->error and die "ssh failed: " . $session->error;
+#	chomp($output);
+#        push(@result,$output);
         }
     log_session('Get:'.Dumper(\@result));
     };
     if ($@) { log_error("Abort: $@"); return 0; };
     }
-if ($proto eq 'tssh') {
-    my $t = Net::OpenSSH->new($device->{ip},
-	    user=>$device->{login},
-	    password=>$device->{password},
-	    port=>$device->{port},
-	    timeout=>30,
-	    master_opts => [ 
-	    -o => "StrictHostKeyChecking=no", 
-	    -o => "PubkeyAcceptedKeyTypes=+ssh-dss", 
-	    -o => "KexAlgorithms=+diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1",
-	    -o => "HostKeyAlgorithms=+ssh-dss",
-	    -o => "LogLevel=quiet",
-	    -o => "UserKnownHostsFile=/dev/null"
-	    ]
-	    );
-    if ($t->error) {  log_error("Login to $device->{device_name} ip: $device->{ip} by ssh aborted: ".$t->error); }
-    my ($pty, $pid) = $t->open2pty({stderr_to_stdout => 1}) or die "unable to start remote shell: " . $t->error;
-    my $telnet = Net::Telnet->new(-fhopen => $pty, -prompt => "/$switch_auth{$device->{vendor_id}}{prompt}/", -telnetmode => 0,-cmd_remove_mode => 1,-output_record_separator => "\r");
-    $telnet->waitfor(-match => $telnet->prompt, -errmode => "return") or die "login failed: " . $telnet->lastline;
-    if (exists $switch_auth{$device->{vendor_id}}{enable}) {
-            $telnet->print($switch_auth{$device->{vendor_id}}{enable});
-            $telnet->print($device->{enable_password});
-            $telnet->waitfor("/$switch_auth{$device->{vendor_id}}{prompt}/");
-            }
-    if (!$telnet_version) { $telnet_version = 1; }
+
+if ($device->{proto} eq 'essh') {
     eval {
     foreach my $run_cmd (@tmp) {
         next if (!$run_cmd);
-        my @ret=();
-        @ret=log_cmd($telnet,$run_cmd) if ($telnet_version == 1);
-        @ret=log_cmd2($telnet,$run_cmd) if ($telnet_version == 2);
-        @ret=log_cmd3($telnet,$run_cmd) if ($telnet_version == 3);
-        @ret=log_cmd4($telnet,$run_cmd) if ($telnet_version == 4);
-        if (scalar @ret) { push(@result,@ret); }
+        if ($run_cmd =~ /SLEEP/i) {
+            if ($run_cmd =~ /SLEEP\s+(\d+)/i) { log_session('WAIT:'." $1 sec."); sleep($1); } else { log_session('WAIT:'." 10 sec."); sleep(10); };
+            next;
+            }
+        log_session('Send:'.$run_cmd);
+        $session->send("$run_cmd\n");
         select(undef, undef, undef, 0.25);
+        $session->expect(10, -re => qr/$device->{prompt}/);
+	push(@result,$session->before());
         }
+    log_session('Get:'.Dumper(\@result));
     };
-    $telnet->close;
-    waitpid($pid, 0);
     if ($@) { log_error("Abort: $@"); return 0; };
     }
-if ($proto eq 'telnet') {
+
+if ($device->{proto} eq 'telnet') {
     if (!$telnet_version) { $telnet_version = 1; }
     eval {
     foreach my $run_cmd (@tmp) {
@@ -476,7 +472,7 @@ if ($device->{vendor_id} eq '2') {
     eval {
         my $session = netdev_login($device);
         my $cmd = "upload startup-config tftp $tftp_ip $device->{device_name}.cfg";
-        netdev_cmd($device,$session,$switch_auth{$device->{vendor_id}}{proto},$cmd,1);
+        netdev_cmd($device,$session,$cmd,1);
         };
     }
 
@@ -484,7 +480,7 @@ if ($device->{vendor_id} eq '2') {
 if ($device->{vendor_id} eq '3') {
     eval {
         my $cmd = "quit\ntftp $tftp_ip put vrpcfg.zip $device->{device_name}.zip\nSLEEP 5\n";
-        netdev_cmd($device,undef,$switch_auth{$device->{vendor_id}}{proto},$cmd,3);
+        netdev_cmd($device,undef,$cmd,3);
         };
     }
 
@@ -493,7 +489,7 @@ if ($device->{vendor_id} eq '4') {
     eval {
         my $session = netdev_login($device);
         my $cmd = "copy running-config tftp $tftp_ip $device->{device_name}.cfg";
-        netdev_cmd($device,$session,$switch_auth{$device->{vendor_id}}{proto},$cmd,1);
+        netdev_cmd($device,$session,$cmd,1);
         };
     }
 
@@ -502,7 +498,7 @@ if ($device->{vendor_id} eq '5') {
     eval {
         my $session = netdev_login($device);
         my $cmd = "upload startup-config tftp $tftp_ip $device->{device_name}.cfg";
-        netdev_cmd($device,$session,$switch_auth{$device->{vendor_id}}{proto},$cmd,1);
+        netdev_cmd($device,$session,$cmd,1);
         };
     }
 
@@ -513,7 +509,7 @@ if ($device->{vendor_id} eq '6') {
 my $cmd = "copy running-config tftp://$tftp_ip/$device->{device_name}.cfg
 Y
 ";
-        netdev_cmd($device,$session,$switch_auth{$device->{vendor_id}}{proto},$cmd,3);
+        netdev_cmd($device,$session,$cmd,3);
         };
     }
 
@@ -522,7 +518,7 @@ if ($device->{vendor_id} eq '7') {
     eval {
         my $session = netdev_login($device);
         my $cmd = "upload cfg_toTFTP $tftp_ip dest_file $device->{device_name}.cfg src_file config.cfg";
-        netdev_cmd($device,$session,$switch_auth{$device->{vendor_id}}{proto},$cmd,1);
+        netdev_cmd($device,$session,$cmd,1);
         };
     }
 
@@ -537,7 +533,7 @@ SLEEP 2
 $device->{device_name}.cfg
 SLEEP 5
 ";
-    netdev_cmd($device,$session,$switch_auth{$device->{vendor_id}}{proto},$cmd,2);
+    netdev_cmd($device,$session,$cmd,2);
     };
     }
 #allied telesys 8000
@@ -545,7 +541,7 @@ if ($device->{device_model_id} eq '3') {
     eval {
         my $session = netdev_login($device);
         my $cmd = "copy running-config tftp://$tftp_ip/$device->{device_name}.cfg";
-        netdev_cmd($device,$session,$switch_auth{$device->{vendor_id}}{proto},$cmd,2);
+        netdev_cmd($device,$session,$cmd,2);
         };
     }
 #allied telesys 8100
@@ -553,7 +549,7 @@ if ($device->{device_model_id} eq '4') {
     eval {
         my $session = netdev_login($device);
         my $cmd = "copy flash tftp $tftp_ip boot.cfg";
-        netdev_cmd($device,$session,$switch_auth{$device->{vendor_id}}{proto},$cmd,2);
+        netdev_cmd($device,$session,$cmd,2);
         rename $tftp_dir."/boot.cfg",$tftp_dir."/$device->{device_name}".".cfg";
         };
     }
@@ -564,7 +560,7 @@ if ($device->{vendor_id} eq '9') {
         my $session = netdev_login($device);
         log_cmd($session,"/system note set show-at-login=no",1,$session->prompt);
         my $cmd = "/export";
-        my @netdev_cfg = netdev_cmd($device,$session,$switch_auth{$device->{vendor_id}}{proto},$cmd,4);
+        my @netdev_cfg = netdev_cmd($device,$session,$cmd,4);
         write_to_file($tftp_dir."/$device->{device_name}.cfg","Config for $device->{device_name}",0);
         foreach my $row (@netdev_cfg) { write_to_file($tftp_dir."/$device->{device_name}.cfg",$row,1); }
         };
@@ -582,7 +578,7 @@ SLEEP 2
 $device->{device_name}.cfg
 SLEEP 5
 ";
-    netdev_cmd($device,$session,$switch_auth{$device->{vendor_id}}{proto},$cmd,2);
+    netdev_cmd($device,$session,$cmd,2);
     };
     }
 
@@ -596,7 +592,7 @@ copy running-config tftp $tftp_ip $device->{device_name}.cfg
 SLEEP 5
 exit
 ";
-    netdev_cmd($device,$session,$switch_auth{$device->{vendor_id}}{proto},$cmd,1);
+    netdev_cmd($device,$session,$cmd,1);
     };
     }
 
@@ -605,7 +601,7 @@ if ($device->{vendor_id} eq '38') {
     eval {
         my $session = netdev_login($device);
         my $cmd = "upload configuration tftp $tftp_ip $device->{device_name}.cfg";
-        netdev_cmd($device,$session,$switch_auth{$device->{vendor_id}}{proto},$cmd,1);
+        netdev_cmd($device,$session,$cmd,1);
         };
     }
 
@@ -614,7 +610,7 @@ if ($device->{vendor_id} eq '39') {
     eval {
         my $session = netdev_login($device);
         my $cmd = "upload configuration $tftp_ip $device->{device_name}.cfg vr \"VR-Default\"";
-        netdev_cmd($device,$session,$switch_auth{$device->{vendor_id}}{proto},$cmd,1);
+        netdev_cmd($device,$session,$cmd,1);
         };
     }
 }
@@ -678,7 +674,7 @@ exit";
 
 #SNR
 if ($device->{vendor_id} eq '6') {
-$telnet_cmd_mode = 1;
+    $telnet_cmd_mode = 1;
     if (!$descr) { $descr = "no description"; } else { $descr = "description $descr"; }
 $cmd = "
 conf t
@@ -778,7 +774,7 @@ if ($device->{vendor_id} eq '39') {
         }
     }
 
-netdev_cmd($device,$session,$switch_auth{$device->{vendor_id}}{proto},$cmd,$telnet_cmd_mode);
+netdev_cmd($device,$session,$cmd,$telnet_cmd_mode);
 }
 
 #---------------------------------------------------------------------------------
@@ -896,7 +892,7 @@ if ($device->{vendor_id} eq '39') {
     $cmd = "configure snmp sysName $device->{device_name}";
     }
 
-netdev_cmd($device,$session,$switch_auth{$device->{vendor_id}}{proto},$cmd,$telnet_cmd_mode);
+netdev_cmd($device,$session,$cmd,$telnet_cmd_mode);
 }
 
 #---------------------------------------------------------------------------------
@@ -977,7 +973,7 @@ Y
 #Extreme
 if ($device->{vendor_id} eq '39') { $cmd="save configuration primary"; }
 
-netdev_cmd($device,$session,$switch_auth{$device->{vendor_id}}{proto},$cmd,$telnet_cmd_mode);
+netdev_cmd($device,$session,$cmd,$telnet_cmd_mode);
 }
 
 #---------------------------------------------------------------------------------

+ 37 - 30
scripts/eyelib/config.pm

@@ -124,22 +124,28 @@ our @FN=split("/",$0);
 ### script pid file name
 
 $config_ref{my_name}=$FN[-1];
-$config_ref{pid_file}="/var/run/".$FN[-1];
-$config_ref{log_dir}=$Config->{_}->{log_dir} || '/opt/Eye/scripts/log';
-$config_ref{log_common}=$config_ref{log_dir}."/$FN[-1].log";
-$config_ref{dhcpd_conf}=$Config->{_}->{dhcpd_conf} || "/etc/dnsmasq.d";
-$config_ref{DBTYPE}	= $Config->{_}->{DBTYPE} || 'mysql';
-$config_ref{DBHOST}	= $Config->{_}->{DBSERVER} || '127.0.0.1';
-$config_ref{DBNAME}	= $Config->{_}->{DBNAME} || "stat";
-$config_ref{DBUSER}	= $Config->{_}->{DBUSER} || "rstat";
-$config_ref{DBPASS}	= $Config->{_}->{DBPASS} || "rstat";
-$config_ref{domain_auth}= $Config->{_}->{domain_auth} || 'Administrator%password';
-$config_ref{winexe}	= $Config->{_}->{winexe} || '/usr/bin/winexe';
-$config_ref{fping}	= $Config->{_}->{fping} || '/sbin/fping';
-#$config_ref{log_owner_user}= $Config->{_}->{user} || 'nagios';
-$config_ref{log_owner_user}= $Config->{_}->{user} || 'tcpdump';
-#$config_ref{log_owner_group}= $Config->{_}->{group} || 'nagios';
-$config_ref{log_owner_group}= $Config->{_}->{group} || 'tcpdump';
+
+$config_ref{pid_dir} ='/run';
+
+#for run as root - use /run dir for pid files
+if ($> > 0) {
+    $config_ref{pid_dir}=$HOME_DIR.'/run';
+    }
+
+$config_ref{pid_file}       = $config_ref{pid_dir}."/".$FN[-1];
+$config_ref{log_dir}        = $Config->{_}->{log_dir} || $HOME_DIR.'/log';
+$config_ref{log_common}     = $config_ref{log_dir}."/$FN[-1].log";
+$config_ref{dhcpd_conf}     = $Config->{_}->{dhcpd_conf} || "/etc/dnsmasq.d";
+$config_ref{DBTYPE}	    = $Config->{_}->{DBTYPE} || 'mysql';
+$config_ref{DBHOST}	    = $Config->{_}->{DBSERVER} || '127.0.0.1';
+$config_ref{DBNAME}	    = $Config->{_}->{DBNAME} || "stat";
+$config_ref{DBUSER}	    = $Config->{_}->{DBUSER} || "rstat";
+$config_ref{DBPASS}	    = $Config->{_}->{DBPASS} || "rstat";
+$config_ref{domain_auth}    = $Config->{_}->{domain_auth} || 'Administrator%password';
+$config_ref{winexe}	    = $Config->{_}->{winexe} || '/usr/bin/winexe';
+$config_ref{fping}	    = $Config->{_}->{fping} || '/sbin/fping';
+$config_ref{log_owner_user} = $Config->{_}->{user} || 'eye';
+$config_ref{log_owner_group}= $Config->{_}->{group} || 'eye';
 
 $config_ref{nagios_dir}=$Config->{_}->{nagios_dir} || '/etc/nagios4';
 $config_ref{nagios_dir}=~s/\/$//;
@@ -150,10 +156,10 @@ $config_ref{encryption_key}=$Config->{_}->{encryption_key} || '!!!CHANGE_ME!!!';
 $config_ref{encryption_iv}=$Config->{_}->{encryption_iv} || '123456782345';
 
 our $MY_NAME=$FN[-1];
-our $SPID="/var/run/".$FN[-1];
+our $SPID=$config_ref{pid_file};
 
 #iptables log
-our $LOG_DIR            = $Config->{_}->{log_dir} || '/var/log/scripts';
+our $LOG_DIR            = $config_ref{log_dir};
 our $LOG_COMMON         = "$LOG_DIR/$FN[-1].log";
 
 our $LOG                = $LOG_COMMON;
@@ -191,14 +197,14 @@ our $W_INFO = 0;
 our $W_ERROR = 1;
 our $W_DEBUG = 2;
 
-our $DBHOST 		= $Config->{_}->{DBSERVER} || '127.0.0.1';
-our $DBNAME 		= $Config->{_}->{DBNAME} || "stat";
-our $DBUSER 		= $Config->{_}->{DBUSER} || "rstat";
-our $DBPASS 		= $Config->{_}->{DBPASS} || "rstat";
+our $DBHOST 		= $config_ref{DBHOST};
+our $DBNAME 		= $config_ref{DBNAME};
+our $DBUSER 		= $config_ref{DBUSER};
+our $DBPASS 		= $config_ref{DBPASS};
 
-our $domain_auth	= $Config->{_}->{domain_auth} || 'Administrator%password';
-our $winexe		    = $Config->{_}->{winexe} || '/usr/bin/winexe';
-our $fping		    = $Config->{_}->{fping} || '/sbin/fping';
+our $domain_auth	= $config_ref{domain_auth};
+our $winexe		= $config_ref{winexe};
+our $fping		= $config_ref{fping};
 
 our @subnets=();
 
@@ -206,8 +212,8 @@ our $history_log_day;
 our $history_syslog_day;
 our $history_trafstat_day;
 
-our $log_owner_user	= $Config->{_}->{user} || 'nagios';
-our $log_owner_group	= $Config->{_}->{group} || 'nagios';
+our $log_owner_user	= $config_ref{log_owner_user};
+our $log_owner_group	= $config_ref{log_owner_group};
 
 ################################################################
 
@@ -255,9 +261,9 @@ our $tftp_server=$Config->{_}->{tftp_server} || '';
 our $last_refresh_config = time();
 
 our %switch_auth = (
-'8'=>{'vendor'=>'Allied Telesis','enable'=>'en','proto'=>'telnet','port'=>'23','login'=> '(login|User Name):','password'=>'Password:','prompt'=>qr/(\010\013){0,5}(([-\w]+|[-\w(config)+])\#|[-\w]+\>)/},
-'3'=>{'vendor'=>'Huawei','proto'=>'tssh','port'=>'22','enable'=>'system-view','login'=> 'login as:','password'=>'Password: ','prompt'=>qr/(\<.*\>|\[.*\])/},
-'16'=>{'vendor'=>'Cisco','proto'=>'telnet','port'=>'23','enable'=>'en','login'=> 'Username:','password'=>'Password:','prompt'=>qr/([-\w]+|[-\w(config)+])\#/},
+'8'=>{'vendor'=>'Allied Telesis','enable'=>'en','proto'=>'essh','port'=>'22','login'=> '(login|User Name):','password'=>'Password:','prompt'=>qr/(\010\013){0,5}(([-\w]+|[-\w(config)+])\#|[-\w]+\>)/},
+'3'=>{'vendor'=>'Huawei','proto'=>'essh','port'=>'22','enable'=>'system-view','login'=> 'login as:','password'=>'Password: ','prompt'=>qr/(\<.*\>|\[.*\])/},
+'16'=>{'vendor'=>'Cisco','proto'=>'ssh','port'=>'22','enable'=>'en','login'=> 'Username:','password'=>'Password:','prompt'=>qr/([-\w]+|[-\w(config)+])\#/},
 '5'=>{'vendor'=>'Raisecom','proto'=>'telnet','port'=>'23','enable'=>'en','login'=> 'Login:','password'=>'Password:','prompt'=>qr/([-\w]+|[-\w(config)+])\#/},
 '6'=>{'vendor'=>'SNR','proto'=>'telnet','port'=>'23','login'=> 'login:','password'=>'Password:','prompt'=>qr/([-\w]+|[-\w(config)+])\#/},
 '7'=>{'vendor'=>'Dlink','proto'=>'telnet','port'=>'23','login'=> 'UserName:','password'=>'PassWord:','prompt'=>qr/[-\w]+\#$/},
@@ -271,6 +277,7 @@ our %switch_auth = (
 );
 
 mkdir $LOG_DIR unless (-d $LOG_DIR);
+mkdir $config_ref{pid_dir} unless (-d $config_ref{pid_dir});
 
 my @cpu_list = `grep ^processor /proc/cpuinfo`;
 $cpu_count = scalar @cpu_list;

+ 12 - 1
scripts/eyelib/main.pm

@@ -560,9 +560,20 @@ $device->{password}=$config_ref{router_password} if (!$device->{password});
 $device->{password}=decrypt_string($device->{password});
 $device->{enable_password}='';
 #$device->{enable_password}=$device->{passowrd};
-$device->{proto} = 'ssh' if ($device->{protocol} eq '0');
+$device->{proto} = 'ssh';
 $device->{proto} = 'telnet' if ($device->{protocol} eq '1');
+#patch for ssh
+if ($device->{proto} == 'ssh' and exists $switch_auth{$device->{vendor_id}}{proto}) {
+	#set specified ssh type
+	if ($switch_auth{$device->{vendor_id}}{proto} =~/ssh/i) {
+		$device->{proto} = $switch_auth{$device->{vendor_id}}{proto};
+		}
+	}
 $device->{port} = $device->{control_port} if ($device->{control_port});
+$device->{prompt} = qr/[\$#>]\s?$/;
+if (exists $switch_auth{$device->{vendor_id}}) {
+    $device->{prompt} = $switch_auth{$device->{vendor_id}}{prompt} if ($switch_auth{$device->{vendor_id}}{prompt});
+    }
 return $device;
 }
 

+ 11 - 9
scripts/utils/set_port_descr.pl

@@ -44,8 +44,7 @@ $auth_ref{$auth->{id}}{device}=$a_netdev;
 if ($auth->{dns_name}) { $auth_ref{$auth->{id}}{description} = $auth->{dns_name}; }
 if (!$auth_ref{$auth->{id}}{description} and $auth->{WikiName}) { $auth_ref{$auth->{id}}{description} = $auth->{WikiName}; }
 if (!$auth_ref{$auth->{id}}{description} and $auth->{comments}) { $auth_ref{$auth->{id}}{description} = translit($auth->{comments}); }
-if (!$auth_ref{$auth->{id}}{description} and $auth->{dhcp_hostname}) { $auth_ref{$auth->{id}}{description} = $auth->{dhcp_hostname}; }
-if (!$auth_ref{$auth->{id}}{description}) { $auth_ref{$auth->{id}}{description} = translit($auth->{login})."_".$auth->{ip}; }
+if (!$auth_ref{$auth->{id}}{description}) { $auth_ref{$auth->{id}}{description} = $auth->{ip}; }
 $auth_ref{$auth->{id}}{description}=~s/\./-/g;
 $auth_ref{$auth->{id}}{description}=~s/\(/_/g;
 $auth_ref{$auth->{id}}{description}=~s/\)/_/g;
@@ -55,14 +54,14 @@ my %port_info;
 
 my $d_sql="SELECT DP.id, D.ip, D.device_name, D.device_model_id, DP.port, DP.snmp_index, DP.comment, D.community, D.snmp_version, DP.target_port_id, D.vendor_id, D.device_type
 FROM devices AS D, device_ports AS DP
-WHERE D.snmp_version>0 and D.id = DP.device_id AND D.community IS NOT NULL AND (D.device_type = 1 OR D.device_type=2) AND D.deleted=0
+WHERE D.snmp_version>0 and D.id = DP.device_id AND D.community IS NOT NULL AND (D.device_type <=1) AND D.deleted=0
 ORDER BY D.device_name,DP.port";
 
 my @port_list = get_records_sql($dbh,$d_sql);
 
 foreach my $port (@port_list) {
 $port_info{$port->{id}}{id}=$port->{id};
-$port_info{$port->{id}}{device_name}=$port->{device_name};
+$port_info{$port->{id}}{device_name}=lc($port->{device_name});
 $port_info{$port->{id}}{ip}=$port->{ip};
 $port_info{$port->{id}}{device_model_id}=$port->{device_model_id};
 $port_info{$port->{id}}{port}=$port->{port};
@@ -85,7 +84,7 @@ $conn_info{$conn->{id}}{id}=$conn->{id};
 $conn_info{$conn->{id}}{port_id}=$conn->{port_id};
 if ($conn->{auth_id}) {
     $conn_info{$conn->{id}}{auth_id}=$conn->{auth_id};
-    $conn_info{$conn->{id}}{description}=$auth_ref{$conn->{auth_id}}->{description}."==ID:".$conn->{auth_id};
+    $conn_info{$conn->{id}}{description}=$auth_ref{$conn->{auth_id}}->{description};
     $conn_info{$conn->{id}}{ou_id}=$auth_ref{$conn->{auth_id}}->{ou_id};
     }
 }
@@ -114,7 +113,7 @@ my %devices;
 
 foreach my $port_id (keys %port_info) {
 if ($port_info{$port_id}{target_port_id}) {
-    $port_info{$port_id}{description}=$port_info{$port_info{$port_id}{target_port_id}}{device_name}."-port-".$port_info{$port_info{$port_id}{target_port_id}}{port};
+    $port_info{$port_id}{description}=$port_info{$port_info{$port_id}{target_port_id}}{device_name}." [".$port_info{$port_info{$port_id}{target_port_id}}{port}.']';
     }
 if (!$port_info{$port_id}{description} and $port_info{$port_id}{comment}) { $port_info{$port_id}{description}=translit($port_info{$port_id}{comment}); }
 $devices{$port_info{$port_id}{device_name}}{ports}{$port_info{$port_id}{port}}{description}=$port_info{$port_id}{description};
@@ -128,7 +127,10 @@ $devices{$port_info{$port_id}{device_name}}{community}=$port_info{$port_id}{comm
 $devices{$port_info{$port_id}{device_name}}{snmp_version}=$port_info{$port_id}{snmp_version};
 }
 
-foreach my $device_name (keys %devices) {
+
+$Net::OpenSSH::debug=-1;
+
+foreach my $device_name (sort keys %devices) {
 my $device = $devices{$device_name};
 
 #skip unknown vendor
@@ -168,17 +170,17 @@ if ($session) {
     foreach my $port (sort  { $a <=> $b } keys %{$device->{ports}}) {
         my $descr = $device->{ports}{$port}{description};
         next if ($descr =~ /^-port-$/);
+        next if ($descr =~ /^\s+\[\]$/);
         my $index = $device->{ports}{$port}{snmp_index};
         print "Port: $port index: $index Descr: $descr\n";
         netdev_set_port_descr($session,$device,$int->{$index}->{name},$port,$descr);
         }
     netdev_wr_mem($session,$device);
-    }
+    } else { print "Login error!\n"; next; }
 };
 if ($@) { print "Error! Apply failed!\n"; next; }
 
 print "Programming finished.\n";
-
 }
 
 exit;