From 18c3618e2833e9296c6cc23e6e3d4b5acff3a3bc Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Wed, 11 Jul 2018 14:43:59 -0500 Subject: [PATCH] Arp tool (#2155) * let cmake set path to arp * declare cameras array * fix probeV4L function * typo * fix another typo - my machine is possessed. * update redhat, debian, ubuntu build dependencies --- CMakeLists.txt | 18 +++ distros/debian/control | 1 + distros/redhat/zoneminder.spec | 1 + distros/ubuntu1604/control | 2 + web/skins/classic/views/monitorprobe.php | 136 ++++++++++------------- 5 files changed, 80 insertions(+), 78 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c847e06a3..6d070c6d3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -802,6 +802,24 @@ if(WITH_SYSTEMD) endif(NOT POLKIT_FOUND) endif(WITH_SYSTEMD) +# Find the path to an arp compatible executable +if(ZM_PATH_ARP STREQUAL "") + find_program(ARP_EXECUTABLE arp) + if(ARP_EXECUTABLE) + set(ZM_PATH_ARP "${ARP_EXECUTABLE}") + mark_as_advanced(ARP_EXECUTABLE) + else(ARP_EXECUTABLE) + find_program(ARP_EXECUTABLE ip) + if(ARP_EXECUTABLE) + set(ZM_PATH_ARP "${ARP_EXECUTABLE} neigh") + mark_as_advanced(ARP_EXECUTABLE) + endif(ARP_EXECUTABLE) + endif(ARP_EXECUTABLE) + if(ARP_EXECUTABLE-NOTFOUND) + message(WARNING "Unable to find a compatible arp binary. Monitor probe will not function." ) + endif(ARP_EXECUTABLE-NOTFOUND) +endif(ZM_PATH_ARP STREQUAL "") + # Some variables that zm expects set(ZM_PID "${ZM_RUNDIR}/zm.pid") set(ZM_CONFIG "${ZM_CONFIG_DIR}/zm.conf") diff --git a/distros/debian/control b/distros/debian/control index 9de030e87..29be56e25 100644 --- a/distros/debian/control +++ b/distros/debian/control @@ -13,6 +13,7 @@ Build-Depends: debhelper (>= 9), cmake , libv4l-dev (>= 0.8.3) , libbz2-dev , ffmpeg | libav-tools + , net-tools , libnetpbm10-dev , libvlccore-dev, libvlc-dev , libcurl4-gnutls-dev | libcurl4-nss-dev | libcurl4-openssl-dev diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec index e3eb2abab..a9278891e 100644 --- a/distros/redhat/zoneminder.spec +++ b/distros/redhat/zoneminder.spec @@ -52,6 +52,7 @@ BuildRequires: pcre-devel BuildRequires: libjpeg-turbo-devel BuildRequires: findutils BuildRequires: coreutils +BuildRequires: net-tools BuildRequires: perl BuildRequires: perl-generators BuildRequires: perl(Archive::Tar) diff --git a/distros/ubuntu1604/control b/distros/ubuntu1604/control index 0b934b7d2..3054a2d55 100644 --- a/distros/ubuntu1604/control +++ b/distros/ubuntu1604/control @@ -11,6 +11,8 @@ Build-Depends: debhelper (>= 9), dh-systemd, python-sphinx | python3-sphinx, apa ,libavformat-dev (>= 6:10~) ,libavutil-dev (>= 6:10~) ,libswscale-dev (>= 6:10~) + ,ffmpeg | libav-tools + ,net-tools ,libbz2-dev ,libgcrypt-dev | libgcrypt11-dev ,libcurl4-gnutls-dev diff --git a/web/skins/classic/views/monitorprobe.php b/web/skins/classic/views/monitorprobe.php index 0717d1fca..14be96f48 100644 --- a/web/skins/classic/views/monitorprobe.php +++ b/web/skins/classic/views/monitorprobe.php @@ -26,7 +26,7 @@ if ( !canEdit('Monitors') ) { // Probe Local Cameras function probeV4L() { - $cameras = array(); + $cameras = array(); $command = getZmuCommand(' --query --device'); if ( !empty($_REQUEST['device']) ) @@ -110,6 +110,7 @@ function probeV4L() { $device['inputs'] = $inputs; $devices[] = $device; } # end foreach output line + return $cameras; } # end function probeV4L // Probe Network Cameras @@ -206,7 +207,7 @@ function probeVivotek($ip) { 'Width' => 352, 'Height' => 240, ), - ); + );t if ( $lines = @file($url) ) { foreach ( $lines as $line ) { $line = rtrim($line); @@ -242,91 +243,70 @@ function probeWansview($ip) { } function probeNetwork() { - // Calling arp without the full path was reported to fail on some systems - // Use the builtin unix command "type" to tell us where the command is - $arp_command = ''; - $result = explode(' ', ZM_PATH_ARP); - if ( !is_executable($result[0]) ) { - if ( ZM_PATH_ARP ) { - Warning("User assigned ARP tool not found. Verify ZM_PATH_ARP points to a valid arp tool and is executable by the web user account."); - } - $result = exec('type -p arp', $output, $status); - if ( $status ) { - Warning("Unable to determine path for arp command, type -p arp returned '$status' output is: " . implode("\n", $output)); - unset($output); - $result = exec('which arp', $output, $status); - if ( $status ) { - Warning("Unable to determine path for arp command, which arp returned '$status'"); - if ( file_exists('/usr/sbin/arp') ) { - $arp_command = '/usr/sbin/arp -a'; - } - } else { - $arp_command = $output[0].' -a'; - } - } else { - $arp_command = $output[0].' -a'; - } - } else { - $arp_command = ZM_PATH_ARP; - } - // Now that we know where arp is, call it using the full path - unset($output); - $result = exec(escapeshellcmd($arp_command), $output, $status); - if ( $status ) { - Error("Unable to probe network cameras, status is '$status'"); - return; - } + $cameras = array(); + $arp_command = ZM_PATH_ARP; + $result = explode(' ', $arp_command); + if ( !is_executable($result[0]) ) { + Error("ARP compatible binary not found or not executable by the web user account. Verify ZM_PATH_ARP points to a valid arp tool."); + return; + } - $monitors = array(); - foreach ( dbFetchAll("SELECT Id, Name, Host FROM Monitors WHERE Type = 'Remote' ORDER BY Host") as $monitor ) { - if ( preg_match('/^(.+)@(.+)$/', $monitor['Host'], $matches) ) { - //echo "1: ".$matches[2]." = ".gethostbyname($matches[2])."
"; - $monitors[gethostbyname($matches[2])] = $monitor; - } else { - //echo "2: ".$monitor['Host']." = ".gethostbyname($monitor['Host'])."
"; - $monitors[gethostbyname($monitor['Host'])] = $monitor; - } - } + $result = exec(escapeshellcmd($arp_command), $output, $status); + if ( $status ) { + Error("Unable to probe network cameras, status is '$status'"); + return; + } - $macBases = array( - '00:40:8c' => array('type'=>'Axis', 'probeFunc'=>'probeAxis'), - '00:80:f0' => array('type'=>'Panasonic','probeFunc'=>'probePana'), - '00:0f:7c' => array('type'=>'ACTi','probeFunc'=>'probeACTi'), - '00:02:d1' => array('type'=>'Vivotek','probeFunc'=>'probeVivotek'), - '7c:dd:90' => array('type'=>'Wansview','probeFunc'=>'probeWansview'), - '78:a5:dd' => array('type'=>'Wansview','probeFunc'=>'probeWansview') - ); + $monitors = array(); + foreach ( dbFetchAll("SELECT Id, Name, Host FROM Monitors WHERE Type = 'Remote' ORDER BY Host") as $monitor ) { + if ( preg_match('/^(.+)@(.+)$/', $monitor['Host'], $matches) ) { + //echo "1: ".$matches[2]." = ".gethostbyname($matches[2])."
"; + $monitors[gethostbyname($matches[2])] = $monitor; + } else { + //echo "2: ".$monitor['Host']." = ".gethostbyname($monitor['Host'])."
"; + $monitors[gethostbyname($monitor['Host'])] = $monitor; + } + } - foreach ( $output as $line ) { - if ( !preg_match('/(\d+\.\d+\.\d+\.\d+).*(([0-9a-f]{2}:){5})/', $line, $matches) ) - continue; - $ip = $matches[1]; - $host = $ip; - $mac = $matches[2]; - //echo "I:$ip, H:$host, M:$mac
"; - $macRoot = substr($mac,0,8); - if ( isset($macBases[$macRoot]) ) { - $macBase = $macBases[$macRoot]; - $camera = call_user_func($macBase['probeFunc'], $ip); - $sourceDesc = htmlspecialchars(serialize($camera['monitor'])); - $sourceString = $camera['model'].' @ '.$host; - if ( isset($monitors[$ip]) ) { - $monitor = $monitors[$ip]; - $sourceString .= ' ('.$monitor['Name'].')'; - } else { - $sourceString .= ' - '.translate('Available'); - } - $cameras[$sourceDesc] = $sourceString; - } - } # end foreach output line - return $cameras; + $macBases = array( + '00:40:8c' => array('type'=>'Axis', 'probeFunc'=>'probeAxis'), + '00:80:f0' => array('type'=>'Panasonic','probeFunc'=>'probePana'), + '00:0f:7c' => array('type'=>'ACTi','probeFunc'=>'probeACTi'), + '00:02:d1' => array('type'=>'Vivotek','probeFunc'=>'probeVivotek'), + '7c:dd:90' => array('type'=>'Wansview','probeFunc'=>'probeWansview'), + '78:a5:dd' => array('type'=>'Wansview','probeFunc'=>'probeWansview') + ); + + foreach ( $output as $line ) { + if ( !preg_match('/(\d+\.\d+\.\d+\.\d+).*(([0-9a-f]{2}:){5})/', $line, $matches) ) + continue; + $ip = $matches[1]; + $host = $ip; + $mac = $matches[2]; + //echo "I:$ip, H:$host, M:$mac
"; + $macRoot = substr($mac,0,8); + if ( isset($macBases[$macRoot]) ) { + $macBase = $macBases[$macRoot]; + $camera = call_user_func($macBase['probeFunc'], $ip); + $sourceDesc = htmlspecialchars(serialize($camera['monitor'])); + $sourceString = $camera['model'].' @ '.$host; + if ( isset($monitors[$ip]) ) { + $monitor = $monitors[$ip]; + $sourceString .= ' ('.$monitor['Name'].')'; + } else { + $sourceString .= ' - '.translate('Available'); + } + $cameras[$sourceDesc] = $sourceString; + } + } # end foreach output line + return $cameras; } # end function probeNetwork() $cameras = array(); $cameras[0] = translate('ChooseDetectedCamera'); if ( ZM_HAS_V4L2 ) - $cameras += probeV4L(); + $cameras += probeV4L(); $cameras += probeNetwork(); if ( count($cameras) <= 1 )