<% $err %> % $m->comp('SELF:show_age') if $cmd eq 'age';

Report IP Inventory

Finds IP Addresses used by nodes

Netbios Inventory

% $m->comp('SELF:show_nbt') if $cmd eq 'nbt';
<%args> $subnet => '' $subnet_select => '' $subnet_show => 0 $sort => 'IP' $age_val => 2 $age_mul => 'months' $cmd => '' $max => 256 @domain => () $archive => 0 $never => 0 $dns => 1 $type => 'all' <%shared> my @sorts = qw/IP Age/; my ($ips,$arg_sort,$odd,$arg_max,$arg_domain,$addrs,$err,$arg_dns); my $nodes = []; my $domain_count = {}; my $nbt_domains={}; my $subnets = []; my $domain = $netdisco::CONFIG{domain} || ''; my $have_nbt_names = 0; <%init> $arg_sort = $sort; $arg_max = $max; $arg_domain = \@domain; $arg_dns = $dns; # If you're just visiting for the first time, set the never checkbox. # If you've submitted a query, though, leave never alone. Can't # default it to 1 in %args since it's a checkbox so no value is # submitted if it's not checked. if (%ARGS == 0) { $never = 1; } # get some form filler my $n1 = time; # I admit, this 'group by' is an ugly kludge :) -m $nbt_domains = sql_column('node_nbt group by domain',['distinct(domain)','count(*)']); my $n2 = time; delete $nbt_domains->{''}; # Get the rows from the subnets table that have # node or device addresses. my $s1 = time; if ($subnet_show) { #BROKEN ON NEWNOC maxb 4/27 -- takes too long at 96 seconds $subnets = active_subnets(); } my $s2 = time; $subnet = $subnet_select if ($subnet_select ne ''); if ($cmd eq 'age' and !$subnet){ $err = "Subnet Required."; $cmd = ''; } if ($cmd eq 'age'){ # Make new column in sql results 'is_old' that is boolean and # tells if we match the aging characteristic. Default to all # matching for type eq 'all'. my @col = ('true as is_old'); if ($type eq 'age') { $age_val = 2 unless $age_val =~ m/^\d+$/; $age_mul =~ s/[^a-z ]+//g; @col = ("(age(now(),node_ip.time_last) >= interval '$age_val $age_mul') as is_old"); } $subnet .= '/24' unless $subnet =~ /\//; my $safenet = dbh_quote($subnet); # Grab all node_ip entries in subnet my $nodes = sql_rows('node_ip LEFT JOIN node_nbt ON node_nbt.ip=node_ip.ip', [@col, 'age(now(),node_ip.time_last) as age', 'extract(epoch from node_ip.time_first) as time_first', 'extract(epoch from node_ip.time_last) as time_last', 'node_ip.ip','node_ip.active', 'node_nbt.domain','node_nbt.nbname', 'node_nbt.active as nbtactive'], { 'node_ip.ip' => \\"<< inet $safenet" } ); # Add all the device / aliases in subnet $col[0] =~ s/node_ip\.time_last/last_discover/; my $devs_seen = sql_rows('device', ['age(now(),last_discover) as age', 'extract(epoch from creation) as time_first','true as active', 'extract(epoch from last_discover) as time_last','ip', @col], { 'ip' => \\"<< inet $safenet"}); $col[0] =~ s/last_discover/d.last_discover/; my $aliases = sql_rows('device_ip a left join device d on a.ip=d.ip', ['age(now(),d.last_discover) as age', 'extract(epoch from a.creation) as time_first','true as active', 'extract(epoch from d.last_discover) as time_last','a.alias as ip',@col], { 'a.alias' => \\"<< inet $safenet"}); # Loop through to find newest entries my %seen; my %results; foreach my $r (@$devs_seen,@$aliases,@$nodes){ my $ip = $r->{ip}; my $is_old = $r->{is_old}; my $am_newest = 0; # First entry unless (defined $seen{$ip} ){ $am_newest++; } # Active entries, but dont overwrite device entries # note that devs and aliases come first elsif ($r->{active} and !$seen{$ip}->{active}) { $am_newest++; } # newest archived data elsif ( $r->{time_last} > $seen{$ip}->{time_last} ) { $am_newest++; } next unless $am_newest; $have_nbt_names ||= defined($r->{nbname}); # Mark down IP as the most relevant and seen $seen{$ip}=$r; next unless $is_old; # Mark down the IP as a match $results{$ip}=$r; } push (@$ips,values %results); # Look for holes in our IP Space and report on that. if ($never){ # Get all the possible IPs in a subnet $addrs = dump_subnet($subnet) || {}; # Remove all the nodes seen in the subnet foreach my $ip (keys %seen) { delete $addrs->{$ip}; } # Add our missing IPs to the results from above. foreach my $ip (keys %$addrs){ push @$ips, { 'age' => 'Never', 'time_first' => 'Never', 'ip' => $ip, 'active' => 1, 'time_last' => 'Never', }; } } # Do DNS lookups on results if ($dns){ foreach my $i (@$ips){ my $ip = $i->{ip}; $i->{dns} = hostname($ip); } } } if ($cmd eq 'nbt'){ my $where = {}; foreach my $d (@domain) { $d = '' if $d eq 'blank'; } if (grep(/^all$/,@domain)){ @domain = (); } else { $where = {'domain' => [[@domain]]}; } $where->{active} = 1 unless $archive; $nodes = sql_rows('node_nbt',['ip','mac','nbname','domain','server','nbuser','active', 'extract(epoch from time_first) as time_first','extract(epoch from time_last) as time_last'], $where); # count domains foreach my $n (@$nodes){ my $d = $n->{domain}; $domain_count->{$d}++; } } %# %# show_nbt() - Show results from Netbios Search %# <%method show_nbt>

Results

% unless (scalar @$nodes) { No Results Found. % return; } % my $cnt = 0; % foreach my $d (sort keys %$domain_count){ % $cnt++; % if ($cnt%2){ %} % if (($cnt+1)%2) { %} %}
Domain Count Domain Count
<%$d || '[Blank]'|h%> <%$domain_count->{$d}%>
<% scalar(keys %$domain_count) %> Domains.

% my $last_domain = ''; % foreach my $n (sort {($a->{domain} cmp $b->{domain}) or % (lc($a->{nbname}) cmp lc($b->{nbname}) )} % @$nodes){ % $last_domain = $n->{domain}; % }
Domain Node Name User First Seen Last Seen
<%$last_domain ne $n->{domain} ? $m->interp->apply_escapes($n->{domain}, 'h') : ' '%> <%$n->{mac}%> <%$n->{domain} ? "\\\\$n->{domain}\\" : '' |h%><%$n->{nbname} || '[None]'|h%> <%$n->{nbuser} || '[No User]' |h%> @ <%$n->{ip}%> <& 'node.html:format_date', date=>$n->{time_first}&> <& 'node.html:format_date', date=>$n->{time_last}&>
<% scalar(@$nodes) %> Nodes.

%# %# show_age() - Show results from IP age inventory %# <%method show_age>

Results

% unless (scalar @$ips) { No Results Found. % return; } % if ($arg_dns) { % } % if ($have_nbt_names) { % } <%perl> my @rows; if ($arg_sort eq 'Age'){ @rows = sort { $a->{time_last} <=> $b->{time_last} } @$ips; } else { @rows = sort sort_ip @$ips; } # Truncate the list if too long (too many results) if (scalar @rows > $arg_max) { splice(@rows,$arg_max); $m->out("Found ".scalar(@$ips) ." matching IPs. Only showing $arg_max.
\n"); } $odd = 1; foreach my $row (@rows){ my $ip = $row->{ip}; my $dns = $row->{dns}; $dns =~ s/\Q$domain\E//; my $age = $m->comp('device_inv.html:.trim_age', age => $row->{age}); my $time_first = $row->{time_first} eq 'Never' ? ' ' : scalar(localtime($row->{time_first})); my $active = $row->{active}; my $d = $row->{domain}; my $nbname = $row->{nbname}; my $nbtactive = $row->{nbtactive}; $odd++; % if ($arg_dns) { % } % if ($have_nbt_names) { % } %}
NodeHost NameNetBIOS
Name
Last Used First
Discovered
<%$ip%><%!$active ? '*' : ''%> % if ($dns) { <%$dns%><%!$active ? '*' : ''%> % } else {   % } % if ($nbname) { \\<%$d%>\<%$nbname%><%!$nbtactive ? '*' : ''%> % } else {   % } <%$age%><%!$active ? '*' : ''%> <%$time_first%>
<% scalar @rows %> IPs Shown.
* denotes archived data (not currently in use, but seen). <%method title> - Node Inventory \ %# $Id$ %# vim:syntax=mason