From f882f9831951654ba3ddd45a7116a11340d8c694 Mon Sep 17 00:00:00 2001 From: Oliver Gorwits Date: Tue, 30 Jun 2020 09:46:19 +0100 Subject: [PATCH] #721 redux - better MAC address support in searching --- Changes | 1 + lib/App/Netdisco/DB/ResultSet/Device.pm | 36 ++++++++++++++++++-- lib/App/Netdisco/Web/Plugin/Search/Device.pm | 5 ++- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/Changes b/Changes index ced54f5a..b9bf1c96 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,7 @@ [ENHANCEMENTS] + * #721 redux - better MAC address support in searching * #728 store SNMP Engine ID [BUG FIXES] diff --git a/lib/App/Netdisco/DB/ResultSet/Device.pm b/lib/App/Netdisco/DB/ResultSet/Device.pm index 806bb6a5..123c47a8 100644 --- a/lib/App/Netdisco/DB/ResultSet/Device.pm +++ b/lib/App/Netdisco/DB/ResultSet/Device.pm @@ -7,6 +7,7 @@ use warnings; use Try::Tiny; use Regexp::Common 'net'; use NetAddr::IP::Lite ':lower'; +use NetAddr::MAC (); require Dancer::Logger; @@ -181,6 +182,10 @@ Can match the C field as a substring. Can match the C field as a substring (usually this field contains a description of the vendor operating system). +=item mac + +Will match exactly the C field of the Device or any of its Interfaces. + =item model Will match exactly the C field. @@ -245,6 +250,13 @@ sub search_by_field { \[ 'substring(me.layers,9-?, 1)::int = 1', $layers ]; } + # get IEEE MAC format + my $mac = NetAddr::MAC->new($p->{mac}); + undef $mac if + ($mac and $mac->as_ieee + and (($mac->as_ieee eq '00:00:00:00:00:00') + or ($mac->as_ieee !~ m/$RE{net}{MAC}/))); + return $rs ->search_rs({}, $attrs) ->search({ @@ -256,6 +268,12 @@ sub search_by_field { ($p->{description} ? ('me.description' => { '-ilike' => "\%$p->{description}\%" }) : ()), + ($mac ? ( + -or => [ + 'me.mac' => $mac->as_ieee, + 'ports.mac' => $mac->as_ieee, + ]) : ()), + ($p->{model} ? ('me.model' => { '-in' => $p->{model} }) : ()), ($p->{os} ? ('me.os' => @@ -283,7 +301,7 @@ sub search_by_field { { order_by => [qw/ me.dns me.ip /], (($p->{dns} or $p->{ip}) ? ( - join => 'device_ips', + join => [qw/device_ips ports/], distinct => 1, ) : ()), } @@ -309,6 +327,8 @@ The following fields are inspected for a match: =item name +=item mac (including port addresses) + =item description =item dns @@ -341,6 +361,14 @@ sub search_fuzzy { ]; } + # get IEEE MAC format + my $mac = NetAddr::MAC->new($q); + undef $mac if + ($mac and $mac->as_ieee + and (($mac->as_ieee eq '00:00:00:00:00:00') + or ($mac->as_ieee !~ m/$RE{net}{MAC}/))); + $mac = ($mac ? $mac->as_ieee : $q); + return $rs->search( { -or => [ @@ -353,6 +381,10 @@ sub search_fuzzy { $rs->search({ 'modules.serial' => $qc }, { join => 'modules', columns => 'ip' })->as_query() }, + -or => [ + 'me.mac::text' => { '-ilike' => $mac}, + 'ports.mac::text' => { '-ilike' => $mac}, + ], -or => [ 'me.dns' => { '-ilike' => $q }, 'device_ips.dns' => { '-ilike' => $q }, @@ -362,7 +394,7 @@ sub search_fuzzy { }, { order_by => [qw/ me.dns me.ip /], - join => 'device_ips', + join => [qw/device_ips ports/], distinct => 1, } ); diff --git a/lib/App/Netdisco/Web/Plugin/Search/Device.pm b/lib/App/Netdisco/Web/Plugin/Search/Device.pm index d7fc878d..3ecdf2d8 100644 --- a/lib/App/Netdisco/Web/Plugin/Search/Device.pm +++ b/lib/App/Netdisco/Web/Plugin/Search/Device.pm @@ -32,6 +32,9 @@ register_search_tab({ description => { description => 'Partial match of the Device description', }, + mac => { + description => 'MAC Address of the Device or any of its Interfaces', + }, model => { description => 'Exact match of the Device model', }, @@ -58,7 +61,7 @@ register_search_tab({ # device with various properties or a default match-all get '/ajax/content/search/device' => require_login sub { my $has_opt = List::MoreUtils::any { param($_) } - qw/name location dns ip description model os os_ver vendor layers/; + qw/name location dns ip description model os os_ver vendor layers mac/; my $rs; if ($has_opt) {