Răsfoiți Sursa

bugfix: Records with other|invalid statuses are excluded from arp processing
html: Optimized the search for records with the same mac in subnets

root 1 săptămână în urmă
părinte
comite
ec71c46089

+ 20 - 40
html/admin/devices/index-passive.php

@@ -4,10 +4,10 @@ require_once ($_SERVER['DOCUMENT_ROOT']."/inc/auth.php");
 require_once ($_SERVER['DOCUMENT_ROOT']."/inc/languages/" . HTML_LANG . ".php");
 require_once ($_SERVER['DOCUMENT_ROOT']."/inc/header.php");
 $default_sort='ip_int';
+require_once ($_SERVER['DOCUMENT_ROOT']."/inc/devmodelsfilter.php");
 require_once ($_SERVER['DOCUMENT_ROOT']."/inc/oufilter.php");
 require_once ($_SERVER['DOCUMENT_ROOT']."/inc/subnetfilter.php");
 require_once ($_SERVER['DOCUMENT_ROOT']."/inc/sortfilter.php");
-require_once ($_SERVER['DOCUMENT_ROOT']."/inc/vendorfilter.php");
 require_once ($_SERVER['DOCUMENT_ROOT']."/inc/devtypesfilter.php");
 require_once ($_SERVER['DOCUMENT_ROOT']."/inc/buildingfilter.php");
 
@@ -15,8 +15,6 @@ $unknown=1;
 if (!isset($_POST['f_unknown']) and isset($_POST['OK'])) { $unknown=0; }
 if (isset($_POST['f_unknown'])) { $unknown=$_POST['f_unknown']*1; }
 
-$params =[];
-
 $unknown_checked='';
 if ($unknown) { $unknown_checked='checked="checked"'; }
 
@@ -27,26 +25,22 @@ if ($sort_field == 'model_name') { $sort_table = 'M'; }
 
 $sort_url = "<a href=index-passive.php?ou=" . $rou;
 
-if ($rou == 0) { $ou_filter = ''; } else { $ou_filter = " and L.ou_id=? "; $params[]=$rou; }
+$filter = '';
+$params =[];
 
-if ($rsubnet == 0) { $subnet_filter = ''; } else {
+if ($f_building_id > 0) { $filter .= ' and D.building_id=?'; $params[]=$f_building_id; }
+if ($f_devtype_id >= 0) { $filter .= ' and D.device_type=?'; $params[]=$f_devtype_id; } else { $filter .= ' and D.device_type> ?'; $params[]=2; }
+if ($f_devmodel_id > 0) { $filter .= ' and D.device_model_id=?'; $params[]= $f_devmodel_id; }
+if ($rou > 0) { $filter .= ' and L.ou_id=? '; $params[]=$rou; }
+if ($rsubnet > 0) {
     $subnet_range = get_subnet_range($db_link,$rsubnet);
     if (!empty($subnet_range)) { 
-        $subnet_filter = " and A.ip_int>=? and A.ip_int<=?";
+        $filter .= " and A.ip_int>=? and A.ip_int<=?";
         $params[]=$subnet_range['start'];
         $params[]=$subnet_range['stop'];
         }
     }
 
-$d_filter='';
-if ($f_building_id > 0) { $d_filter .= ' and D.building_id=?'; $params[]=$f_building_id; }
-if ($f_devtype_id > 0) { 
-    $d_filter .= ' and D.device_type=?'; 
-    $params[]= $f_devtype_id;
-    } else { $d_filter .= ' and D.device_type>2'; }
-
-$ip_list_filter = $ou_filter.$subnet_filter;
-
 unset($_POST);
 
 print_device_submenu($page_url);
@@ -60,7 +54,8 @@ print_device_submenu($page_url);
 <td class="info"> <?php print_devtypes_select($db_link, "devtypes", $f_devtype_id, "id>2"); ?>
 <td class="info"> <?php print WEB_device_show_location; ?></td>
 <td class="info" colspan=2> <?php print_building_select($db_link, "building_id", $f_building_id); ?></td>
-<td class="info" colspan=2 align=right><input name="OK" type="submit" value="<?php echo WEB_btn_show; ?>"></td>
+<td class="info"><?php print WEB_device_hide_unknown."&nbsp"; ?> <input type=checkbox name=f_unknown value="1" <?php print $unknown_checked; ?>> </td>
+<td class="info" align=right><input name="OK" type="submit" value="<?php echo WEB_btn_show; ?>"></td>
 </tr>
 <tr>
 <td class="info"><?php print WEB_cell_ou."&nbsp"; ?> </td>
@@ -68,9 +63,7 @@ print_device_submenu($page_url);
 <td class="info"><?php print WEB_rows_at_page."&nbsp:"; print_row_at_pages('rows',$displayed); ?></td>
 <td class="info"><?php print WEB_network_subnet; ?> </td>
 <td class="info"><?php print_subnet_select_office($db_link, 'subnet', $rsubnet); ?></td>
-<td class="info"><?php print WEB_device_hide_unknown."&nbsp"; ?> <input type=checkbox name=f_unknown value="1" <?php print $unknown_checked; ?>> </td>
-<td class="info"><?php print WEB_model_vendor."&nbsp"; print_vendor_select($db_link,"vendor_select",$f_vendor_select); ?></td>
-</td>
+<td class="info" colspan=2><?php  print WEB_models; print_devmodels_select($db_link, "devmodels", $f_devmodel_id, 'device_type>2'); ?></td>
 </tr>
 </table>
 </form>
@@ -111,17 +104,11 @@ print_device_submenu($page_url);
 
 <?php
 
-$u_filter='';
-if ($unknown and $f_vendor_select==0) { $u_filter=' AND V.id<>1 '; } else {
-    if (!empty($f_vendor_select) and $f_vendor_select>=1) {
-        $u_filter = " AND V.id=? ";
-        $params[]=$f_vendor_select;
-        }
-    }
 
-$countSQL="SELECT Count(*) FROM user_auth A, user_list L, devices D, device_models M, vendors V
-WHERE D.user_id=L.id AND A.ip = D.ip AND D.device_model_id=M.id AND M.vendor_id=V.id AND A.deleted =0
-$u_filter $ip_list_filter $d_filter";
+$countSQL="SELECT Count(*) FROM user_auth A, user_list L, devices D, device_models M
+WHERE D.user_id=L.id AND A.ip = D.ip AND D.device_model_id=M.id AND A.deleted =0
+$filter";
+
 $count_records = get_single_field($db_link,$countSQL, $params);
 $total=ceil($count_records/$displayed);
 if ($page>$total) { $page=$total; }
@@ -146,10 +133,10 @@ print_navigation($page_url,$page,$displayed,$count_records,$total);
     </tr>
 <?php
 
-$sSQL = "SELECT A.id, D.id as dev_id, D.device_type, A.ip, A.mac, A.user_id, L.login, D.description, A.last_found, V.name, M.model_name
-FROM user_auth A, user_list L, devices D, device_models M, vendors V
-WHERE D.user_id=L.id AND A.ip = D.ip AND D.device_model_id=M.id AND M.vendor_id=V.id AND A.deleted =0
-$u_filter $ip_list_filter $d_filter
+$sSQL = "SELECT A.id, D.id as dev_id, D.device_type, A.ip, A.mac, A.user_id, L.login, D.description, A.last_found, M.model_name
+FROM user_auth A, user_list L, devices D, device_models M
+WHERE D.user_id=L.id AND A.ip = D.ip AND D.device_model_id=M.id AND A.deleted =0
+$filter
 ORDER BY $sort_table.$sort_field $order LIMIT ? OFFSET ?";
 $params[]=$displayed;
 $params[]=$start;
@@ -171,13 +158,6 @@ foreach ($users as $user) {
 print "</table>\n";
 print_navigation($page_url,$page,$displayed,$count_records,$total);
 ?>
-<br>
-<table class="data">
-<tr><td><?php echo WEB_color_description; ?></td></tr>
-<tr>
-<td class="warn"><?php echo WEB_color_user_disabled; ?></td>
-<td class="error"><?php echo WEB_color_user_blocked; ?></td>
-</table>
 </form>
 
 <script src="/js/remodal/remodal.min.js"></script>

+ 3 - 10
html/admin/groups/index.php

@@ -5,19 +5,10 @@ require_once ($_SERVER['DOCUMENT_ROOT']."/inc/languages/" . HTML_LANG . ".php");
 // Удаление OU
 if (getPOST("remove") !== null) {
     $fid = getPOST("f_id", null, []);
-    
     if (!empty($fid) && is_array($fid)) {
         foreach ($fid as $val) {
             $val = (int)$val;
-            if ($val <= 0) continue;
-            // Обнуляем привязки в user_list
-            update_records($db_link, "user_list", "ou_id = ?", ['ou_id' => 0], [$val]);
-            // Обнуляем привязки в user_auth
-            update_records($db_link, "user_auth", "ou_id = ?", ['ou_id' => 0], [$val]);
-            // Удаляем правила авторизации
-            delete_records($db_link, "auth_rules", "ou_id = ?", [$val]);
-            // Удаляем сам OU
-            delete_record($db_link, "ou", "id = ?", [$val]);
+            delete_group($db_link,$val);
         }
     }
     header("Location: " . $_SERVER["REQUEST_URI"]);
@@ -60,6 +51,8 @@ foreach ($t_ou as $row) {
     $flag='';
     if ($row['default_users'] == 1) { $flag='D'; }
     if ($row['default_hotspot'] == 1) { $flag='H'; }
+    $rules_count = get_record_sql($db_link, "SELECT COUNT(id) as cnt FROM auth_rules WHERE ou_id=?", [$row['id']]);
+    if (!empty($rules_count) && $rules_count['cnt']>0) { $flag .='['.$rules_count['cnt'].']'; }
     print "<td class=\"data\">$flag</td>\n";
     print "<td class=\"data\">"; print_url($row['ou_name'],"/admin/groups/edit_group.php?id=".$row['id']); print "</td>\n";
     print_yes_no($row['dynamic'],'custom','data');

+ 55 - 68
html/admin/iplist/doubles.php

@@ -56,96 +56,83 @@ print_ip_submenu($page_url);
     <td align=Center><?php print WEB_cell_last_found; ?></td>
     <td align=right><input type="submit" onclick="return confirm('<?php echo WEB_msg_delete; ?>?')" name="removeauth" value="<?php echo WEB_btn_delete; ?>"></td>
 </tr>
+
 <?php
-$sSQL = "SELECT U.id, U.ip, U.mac, U.arp_found, S.subnet as net FROM user_auth U, subnets S WHERE (U.mac IS NOT NULL AND U.mac<>'') 
-AND (U.ip_int BETWEEN S.ip_int_start AND S.ip_int_stop) $cidr_filter AND S.office=1 AND U.deleted=0 ORDER BY net,mac,arp_found";
-$users = get_records_sql($db_link,$sSQL, $params);
+$sSQL = "SELECT U.*, S.subnet as net FROM user_auth U, subnets S 
+WHERE (U.mac IS NOT NULL AND U.mac<>'') AND (U.ip_int BETWEEN S.ip_int_start AND S.ip_int_stop) $cidr_filter AND S.office=1 AND U.deleted=0 
+ORDER BY net,mac,arp_found,id";
+$auth_list = get_records_sql($db_link,$sSQL, $params);
 $f_subnet=NULL;
 $f_mac=NULL;
 $f_id=NULL;
-$printed = NULL;
 $f_index = 0;
 $f_count = 0;
-foreach ($users as $row) {
+foreach ($auth_list as $row) {
+    if (empty($row['mac'])) { continue; }
+    if (empty($row['net'])) { continue; }
     //инициализируем перебор по первой записи
-    if (empty($f_subnet)) { 
-        //сохраняем для обработки
-        $f_subnet = $row['net'];
-        $f_mac=$row['mac'];
-        $f_id=$row['id'];
-        $f_index=0;
-        continue;
+    if (empty($f_subnet)) {
+        $d_params = $params;
+        //считаем сколько у нас дублей
+        $dSQL = "SELECT U.*, S.subnet as net FROM user_auth U, subnets S WHERE S.office=1 AND U.deleted=0  AND (U.ip_int BETWEEN S.ip_int_start AND S.ip_int_stop) $cidr_filter AND U.mac=? AND S.subnet=?";
+        $d_params[]= $row['mac'];
+        $d_params[]= $row['net'];
+        $doubles = get_records_sql($db_link,$dSQL, $d_params);
+        $f_count = count($doubles);
+        if ($f_count > 1) {
+            //сохраняем для обработки
+            $f_subnet = $row['net'];
+            $f_mac=$row['mac'];
+            $f_id=$row['id'];
+            $f_index = 0;
+            } else { continue; }
         }
     //начинаем перебор - проверяем 
     if ($row['net'] === $f_subnet and $row['mac']===$f_mac) {
-        //если первая запись не выводилась - выводим на печать
-        $d_params = $params;
-        if (!isset($printed[$f_id])) {
-            //считаем сколько у нас дублей
-            $dSQL = "SELECT  U.id, U.ip, U.mac, U.arp_found FROM user_auth U WHERE U.deleted=0 AND U.mac=? $cidr_filter";
-            $d_params[]= $f_mac;
-            $doubles = get_records_sql($db_link,$dSQL, $d_params);
-            $f_count = count($doubles);
-
             $f_index++;
-            $user = get_record_sql($db_link,"SELECT * FROM user_auth WHERE id=?", [$f_id]);
-            if (empty($user['arp_found']) || is_empty_datetime($user['arp_found'])) { $user['arp_found'] = ''; }
-            if (empty($user['ts']) || is_empty_datetime($user['ts'])) { $user['ts'] = ''; }
-            if (empty($user['changed_time']) || is_empty_datetime($user['changed_time'])) { $user['changed_time'] = ''; }
+            if (empty($row['arp_found']) || is_empty_datetime($row['arp_found'])) { $row['arp_found'] = ''; }
+            if (empty($row['ts']) || is_empty_datetime($row['ts'])) { $row['ts'] = ''; }
+            if (empty($row['changed_time']) || is_empty_datetime($row['changed_time'])) { $row['changed_time'] = ''; }
             print "<tr align=center>\n";
             $cl = "data";
-            print "<td class=\"data\" style='padding:0'><input type=checkbox name=f_auth_id[] value=".$user["id"];
-            if ($f_index != $f_count) { print " checked"; }
-            print "></td>\n";
-            print "<td class=\"$cl\" ><a href=/admin/users/edituser.php?id=".$user['user_id'].">" . get_login($db_link,$user['user_id']) . "</a></td>\n";
-            print "<td class=\"$cl\" ><a href=/admin/users/editauth.php?id=".$user['id'].">" . $user['ip'] . "</a></td>\n";
-            print "<td class=\"$cl\" >" . expand_mac($db_link,$user['mac']) . "</td>\n";
-            if (isset($user['dhcp_hostname']) and strlen($user['dhcp_hostname']) > 0) {
-                print "<td class=\"$cl\" >".$user['description']." [" . $user['dhcp_hostname'] . "]</td>\n";
-                } else {
-                print "<td class=\"$cl\" >".$user['description']."</td>\n";
+            print "<td class=\"data\" style='padding:0'><input type=checkbox name=f_auth_id[] value=".$row["id"];
+            if ($f_index >1) {
+                $checked = true;
+                $mac_simplified = mac_simplify($row['mac']);
+                $mac_rules = get_records_sql($db_link, "SELECT * FROM auth_rules WHERE rule_type = 2 AND LENGTH(rule) > 0 AND user_id = ?", [ $row['user_id'] ]);
+                foreach ($mac_rules as $rule_row) {
+                    if (!empty($rule_row['rule'])) {
+                        $pattern = '/^' . preg_quote(mac_simplify($rule_row['rule']), '/') . '/';
+                        if (preg_match($pattern, $mac_simplified)) { $checked = false; break; }
+                        }
                 }
-            print "<td class=\"$cl\" >".$user['dns_name']."</td>\n";
-            print "<td class=\"$cl\" >".$user['ts']."</td>\n";
-            print "<td class=\"$cl\" >".$user['last_found']."</td>\n";
-            print "</tr>\n";
-            $printed[$f_id] = 1;
-            }
-        //проверяем текущую запись
-        if (!isset($printed[$row['id']])) {
-            $f_index++;
-            $user = get_record_sql($db_link,"SELECT * FROM user_auth WHERE id=?", [$row['id']]);
-            if (empty($user['arp_found']) || is_empty_datetime($user['arp_found'])) { $user['arp_found'] = ''; }
-            if (empty($user['ts']) || is_empty_datetime($user['ts'])) { $user['ts'] = ''; }
-            if (empty($user['changed_time']) || is_empty_datetime($user['changed_time'])) { $user['changed_time'] = ''; }
-            print "<tr align=center>\n";
-            $cl = "data";
-            print "<td class=\"data\" style='padding:0'><input type=checkbox name=f_auth_id[] value=".$user["id"];
-            if ($f_index != $f_count) { print " checked"; }
-            print " ></td>\n";
-            print "<td class=\"$cl\" ><a href=/admin/users/edituser.php?id=".$user['user_id'].">" . get_login($db_link,$user['user_id']) . "</a></td>\n";
-            print "<td class=\"$cl\" ><a href=/admin/users/editauth.php?id=".$user['id'].">" . $user['ip'] . "</a></td>\n";
-            print "<td class=\"$cl\" >" . expand_mac($db_link,$user['mac']) . "</td>\n";
-            if (isset($user['dhcp_hostname']) and strlen($user['dhcp_hostname']) > 0) {
-                print "<td class=\"$cl\" >".$user['description']." [" . $user['dhcp_hostname'] . "]</td>\n";
+                if ($checked) { print " checked"; }
+                }
+            print "></td>\n";
+            print "<td class=\"$cl\" ><a href=/admin/users/edituser.php?id=".$row['user_id'].">" . get_login($db_link,$row['user_id']) . "</a></td>\n";
+            print "<td class=\"$cl\" ><a href=/admin/users/editauth.php?id=".$row['id'].">" . $row['ip'] . "</a></td>\n";
+            print "<td class=\"$cl\" >" . expand_mac($db_link,$row['mac']) . "</td>\n";
+            if (isset($row['dhcp_hostname']) and strlen($row['dhcp_hostname']) > 0) {
+                print "<td class=\"$cl\" >".$row['description']." [" . $row['dhcp_hostname'] . "]</td>\n";
                 } else {
-                print "<td class=\"$cl\" >".$user['description']."</td>\n";
+                print "<td class=\"$cl\" >".$row['description']."</td>\n";
                 }
-            print "<td class=\"$cl\" >".$user['dns_name']."</td>\n";
-            print "<td class=\"$cl\" >".$user['ts']."</td>\n";
-            print "<td class=\"$cl\" >".$user['last_found']."</td>\n";
+            print "<td class=\"$cl\" >".$row['dns_name']."</td>\n";
+            print "<td class=\"$cl\" >".$row['ts']."</td>\n";
+            print "<td class=\"$cl\" >".$row['last_found']."</td>\n";
+            print "<td class=\"$cl\" ></td>\n";
             print "</tr>\n";
-            $printed[$row['id']] = 1;
-            }
         } else {
-        $f_subnet = $row['net'];
-        $f_mac = $row['mac'];
-        $f_id = $row['id'];
-        $f_index = 0;
+            $f_subnet = NULL;
+            $f_mac = NULL;
+            $f_id = NULL;
+            $f_index = 0;
+            $f_count = 0; 
         }
     }
 print "</table>\n";
 ?>
+
 </form>
 <br>
 <?php

+ 15 - 40
html/inc/common.php

@@ -1607,31 +1607,21 @@ function print_building_select($db, $building_name, $building_value)
     echo "</select>\n";
 }
 
-function print_devmodels_select($db, $devmodel_name, $devmodel_value, $dev_filter = 'device_type<=2')
+function print_devmodels_select($db, $devmodel_name, $devmodel_value, $dev_filter = 'device_type<=2', $vendor_id = NULL)
 {
-    // Валидация фильтра для предотвращения SQL-инъекций
-    $allowed_filters = [
-        'device_type<=2',
-        'device_type=2',
-        'device_type=1',
-        'device_type=0'
-    ];
-    
-    if (!in_array($dev_filter, $allowed_filters)) {
-        $dev_filter = 'device_type<=2';
-    }
-    
+
     echo "<select id=\"" . htmlspecialchars($devmodel_name) . "\" name=\"" . htmlspecialchars($devmodel_name) . "\">\n";
     print_select_item(WEB_select_item_all, -1, $devmodel_value);
-    
-    $t_devmodel = get_records_sql($db,
-        "SELECT M.id, V.name, M.model_name 
+
+    $vendor_filter = "";
+    if (!empty($vendor_id)) { $vendor_filter = " AND vendor_id = $vendor_id";  }
+    $mSQL = "SELECT M.id, V.name, M.model_name 
          FROM device_models M, vendors V 
          WHERE M.vendor_id = V.id 
-           AND M.id IN (SELECT device_model_id FROM devices WHERE $dev_filter) 
-         ORDER BY V.name, M.model_name"
-    );
-    
+           AND M.id IN (SELECT device_model_id FROM devices WHERE $dev_filter $vendor_filter)";
+
+    $t_devmodel = get_records_sql($db, $mSQL . " ORDER BY V.name, M.model_name" );
+
     if (!empty($t_devmodel)) {
         foreach ($t_devmodel as $row) {
             $display = htmlspecialchars($row['name']) . " " . htmlspecialchars($row['model_name']);
@@ -1643,32 +1633,15 @@ function print_devmodels_select($db, $devmodel_name, $devmodel_value, $dev_filte
 
 function print_devtypes_select($db, $devtype_name, $devtype_value, $mode)
 {
-    // Валидация режима для предотвращения SQL-инъекций
-    $allowed_modes = [
-        '',
-        'device_class = 1',
-        'device_class = 2',
-        'device_class <= 2',
-        'id IN (0,1,2)',
-        'id > 0'
-        // Добавьте другие допустимые значения по необходимости
-    ];
-    
-    if (!in_array($mode, $allowed_modes)) {
-        $mode = '';
-    }
-    
     echo "<select id=\"" . htmlspecialchars($devtype_name) . "\" name=\"" . htmlspecialchars($devtype_name) . "\">\n";
     print_select_item(WEB_select_item_all, -1, $devtype_value);
-    
+
     $filter = '';
     if (!empty($mode)) {
         $filter = "WHERE $mode";
     }
-    
     $lang_column = 'name_' . HTML_LANG;
     $t_devtype = get_records_sql($db, "SELECT id, $lang_column FROM device_types $filter ORDER BY $lang_column");
-    
     if (!empty($t_devtype)) {
         foreach ($t_devtype as $row) {
             print_select_item(htmlspecialchars($row[$lang_column]), $row['id'], $devtype_value);
@@ -4671,7 +4644,7 @@ function get_new_user_id($db, $ip, $mac, $hostname)
         );
         foreach ($mac_rules as $row) {
             if (!empty($row['rule'])) {
-                $pattern = '/' . preg_quote(mac_simplify($row['rule']), '/') . '/';
+                $pattern = '/^' . preg_quote(mac_simplify($row['rule']), '/') . '/';
                 if (preg_match($pattern, $mac_simplified)) {
                     $result['user_id'] = (int)$row['user_id'];
                     return $result;
@@ -4724,7 +4697,7 @@ function get_new_user_id($db, $ip, $mac, $hostname)
         );
         foreach ($mac_rules as $row) {
             if (!empty($row['rule'])) {
-                $pattern = '/' . preg_quote(mac_simplify($row['rule']), '/') . '/';
+                $pattern = '/^' . preg_quote(mac_simplify($row['rule']), '/') . '/';
                 if (preg_match($pattern, $mac_simplified)) {
                     $result['ou_id'] = (int)$row['ou_id'];
                     return $result;
@@ -5147,3 +5120,5 @@ $config["init"] = 1;
 
 clean_dns_cache($db_link);
 //clean_unreferensed_rules($db_link);
+
+$config["debug"] = 1;

+ 17 - 0
html/inc/sql.php

@@ -1588,6 +1588,23 @@ delete_records($db, "gateway_subnets","device_id=?",[$id]);
 return $changes;
 }
 
+function delete_group($db,$id = NULL)
+{
+if (empty($id)) { return; }
+if ($id<1) { return; }
+$hotspot_ou = get_const('default_hotspot_ou_id');
+$dhcp_ou = get_const('default_user_ou_id');
+if ($id = $dhcp_ou or $id = $hotspot_ou) { return; }
+// Обнуляем привязки в user_list
+update_records($db, "user_list", "ou_id = ?", ['ou_id' => $dhcp_ou ], [$id]);
+// Обнуляем привязки в user_auth
+update_records($db, "user_auth", "ou_id = ?", ['ou_id' => $dhcp_ou ], [$id]);
+// Удаляем правила авторизации
+delete_records($db, "auth_rules", "ou_id = ?", [$id]);
+// Удаляем сам OU
+delete_record($db, "ou", "id = ?", [$id]);
+}
+
 function record_to_txt($db, $table, $id) {
     $record = get_record_sql($db, 'SELECT * FROM ' . $table . ' WHERE id =?', [ $id ]);
     return hash_to_text($record);

+ 4 - 4
scripts/eyelib/common.pm

@@ -313,7 +313,7 @@ sub get_new_user_id {
             my $rule_clean = mac_simplify($r->{rule});
             # Защита от битых регулярок
             eval {
-                if ($mac =~ /\Q$rule_clean\E/i) {  # \Q...\E — экранируем спецсимволы!
+                if ($mac =~ /^$rule_clean/i) {
                     $result->{user_id} = $r->{user_id};
                     return $result;
                 }
@@ -332,7 +332,7 @@ sub get_new_user_id {
         foreach my $r (@rules) {
             next unless defined $r->{rule};
             eval {
-                if ($hostname =~ /$r->{rule}/i) {
+                if ($hostname =~ /^$r->{rule}/i) {
                     $result->{user_id} = $r->{user_id};
                     return $result;
                 }
@@ -368,7 +368,7 @@ sub get_new_user_id {
             next unless defined $r->{rule};
             my $rule_clean = mac_simplify($r->{rule});
             eval {
-                if ($mac =~ /\Q$rule_clean\E/i) {
+                if ($mac =~ /^$rule_clean/i) {
                     $result->{ou_id} = $r->{ou_id};
                     return $result;
                 }
@@ -387,7 +387,7 @@ sub get_new_user_id {
         foreach my $r (@rules) {
             next unless defined $r->{rule};
             eval {
-                if ($hostname =~ /$r->{rule}/i) {
+                if ($hostname =~ /^$r->{rule}/i) {
                     $result->{ou_id} = $r->{ou_id};
                     return $result;
                 }

+ 47 - 20
scripts/eyelib/snmp.pm

@@ -50,6 +50,7 @@ $ifIndex_map
 $ipAdEntIfIndex
 $arp_oid
 $ipNetToMediaPhysAddress
+$ipNetToMediaType
 $fdb_table_oid
 $fdb_table_oid2
 $dot1qPortVlanEntry
@@ -88,6 +89,12 @@ our $ipAdEntIfIndex ='.1.3.6.1.2.1.4.20.1.2';
 our $arp_oid      ='.1.3.6.1.2.1.3.1.1.2';
 #RFC1213::ipNetToMediaPhysAddress
 our $ipNetToMediaPhysAddress = '.1.3.6.1.2.1.4.22.1.2';
+our $ipNetToMediaType = '.1.3.6.1.2.1.4.22.1.4';
+#.1.3.6.1.2.1.4.22.1.4.3263.10.160.0.137 = INTEGER: invalid(2)
+#.1.3.6.1.2.1.4.22.1.4.3263.10.160.0.138 = INTEGER: dynamic(3)
+#.1.3.6.1.2.1.4.22.1.3.3263.10.160.0.151 = IpAddress: 10.160.0.151
+#.1.3.6.1.2.1.4.22.1.3.3263.10.160.0.152 = IpAddress: 10.160.0.152
+
 #RFC1493::dot1dTpFdbTable
 our $fdb_table_oid ='.1.3.6.1.2.1.17.4.3.1.2';
 #Q-BRIDGE-MIB::dot1qTpFdbPort
@@ -159,35 +166,55 @@ sub get_arp_table {
     my $arp;
     my $arp_table1 = $session->get_table($arp_oid);
     my $arp_table2 = $session->get_table($ipNetToMediaPhysAddress);
+    my $arp_status = $session->get_table($ipNetToMediaType);
     $session->close();
 
+    my %ip_status;
+    if ($arp_status) {
+            foreach my $row (keys(%$arp_status)) {
+                $row=trim($row);
+                my $ip;
+                if ($row=~/\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/) { $ip=$1.".".$2.".".$3.".".$4; }
+                next if (!$ip);
+                $ip_status{$ip} = $arp_status->{$row};
+                }
+            }
+
     if ($arp_table1) {
         foreach my $row (keys(%$arp_table1)) {
-        my ($mac_h) = unpack("H*",$arp_table1->{$row});
-        next if (!$mac_h or $mac_h eq '000000000000' or $mac_h eq 'ffffffffffff');
-        my $mac;
-        if (length($mac_h)==12) { $mac=lc $mac_h; }
-        next if (!$mac);
-        $row=trim($row);
-        my $ip;
-        if ($row=~/\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/) { $ip=$1.".".$2.".".$3.".".$4; }
-        next if (!$ip);
-        $arp->{$ip}=$mac;
+            my ($mac_h) = unpack("H*",$arp_table1->{$row});
+            next if (!$mac_h or $mac_h eq '000000000000' or $mac_h eq 'ffffffffffff');
+            my $mac;
+            if (length($mac_h)==12) { $mac=lc $mac_h; }
+            next if (!$mac);
+            $row=trim($row);
+            my $ip;
+            if ($row=~/\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/) { $ip=$1.".".$2.".".$3.".".$4; }
+            next if (!$ip);
+            if (exists $ip_status{$ip}) {
+                if ($ip_status{$ip} >2) { $arp->{$ip}=$mac; }
+                } else {
+                $arp->{$ip}=$mac;
+                }
         };
     }
 
     if ($arp_table2) {
         foreach my $row (keys(%$arp_table2)) {
-        my ($mac_h) = unpack("H*",$arp_table2->{$row});
-        next if (!$mac_h or $mac_h eq '000000000000' or $mac_h eq 'ffffffffffff');
-        my $mac;
-        if (length($mac_h)==12) { $mac=lc $mac_h; }
-        next if (!$mac);
-        $row=trim($row);
-        my $ip;
-        if ($row=~/\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/) { $ip=$1.".".$2.".".$3.".".$4; }
-        next if (!$ip);
-        $arp->{$ip}=$mac;
+            my ($mac_h) = unpack("H*",$arp_table2->{$row});
+            next if (!$mac_h or $mac_h eq '000000000000' or $mac_h eq 'ffffffffffff');
+            my $mac;
+            if (length($mac_h)==12) { $mac=lc $mac_h; }
+            next if (!$mac);
+            $row=trim($row);
+            my $ip;
+            if ($row=~/\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/) { $ip=$1.".".$2.".".$3.".".$4; }
+            next if (!$ip);
+            if (exists $ip_status{$ip}) {
+                if ($ip_status{$ip} > 2) { $arp->{$ip}=$mac; }
+                } else {
+                $arp->{$ip}=$mac;
+                }
         };
     }