Device View: \ <% defined $device ? "$dns ($devip)" : ''%>

% if (defined $device) { <& SELF:page_nav &> <& SELF:show_ports &> <& SELF:show_device &> <& SELF:show_module &> % } <%args> $ip => '' # Can be IP or hostname $ports => 'all' @port => () # Ports to be shown @portcol => () # Columns to Show for each port $submit => '' # Can have all/hide to control ports $device_age => 'off' $archive => 'off' $node_ip => 'on' # Show the IPs used by each MAC $node_dns => 'on' # Resolve IPs of connected devices $node_nbt => 'on' # Show the NetBIOS Name used by each MAC $timecount => 3 # Ports that have been down for at least this many $timeunit => 'months' # time units are considered to be "free" <%shared> my ($arg_age,$arg_arch,$device,$devip,$arg_node_ip, $model, $arg_ports, $arg_node_dns,$arg_node_nbt,$dns,$vendor,$want_web_link,$web_dns, $arg_timecount,$arg_timeunit); my $valid_time_units = ['days', 'weeks', 'months', 'years']; my $db_ports = []; my $node_ips = {}; my $node_nbts = {}; my @arg_port; my $domain = $netdisco::CONFIG{domain}; my $now = time; my $match = 0; my $odd = 1; # These are switches that we want a link to their web interface. my $web_vendors = $netdisco::CONFIG{web_console_vendors} || {}; my $web_models = $netdisco::CONFIG{web_console_models} || {}; my $vlanctl = $netdisco::CONFIG{vlanctl}; my $user = $m->session->{user}; my $secure = &is_secure; my $port_ctl = $m->session->{user_port_ctl}; my $port_control = ($port_ctl and $secure); my $vlan_ctl = ($port_ctl and $secure and $vlanctl); my $port_info = (defined $netdisco::CONFIG{port_info} and $netdisco::CONFIG{port_info} =~ /(1|t|T|y|Y)/) ? 1 : 0; my $admin = defined $m->session->{user_admin} and $m->session->{user_admin} ? 1 : 0; my %modules = {}; # Define the columns that we can show, the default order and whether they are shown by default # Structure: # Key - hashkey, also defines which DB column to display (can be overridden by "data" attribute) # header - required, text to display as column header. # legend - optional, text to display in "Change View" section. Value for "header" is used by default, "legend" overrides. # order - required, integer to indicate default display order for columns. # show - required, column is shown if this evaluates to a true value. Defaults here, can be overridden by arguments. # data - optional, when data to display isn't just the value of a DB columns but comes from a sub or Mason component. # * scalar is interpreted as a Mason component name. Called with $dev, $port and $col arguments. # * coderef if executed, with a hashref as argument containing dev, port and col keys. # noesc - optional, don't perform "|h" HTML escaping on output # (noesc on Mason component means the component will be scomp()'ed, not comp()'ed) # # Actual processing is done in show_ports() component. my %port_cols = ( port => { header => 'Port', order => 1, show => 1, }, descr => { header => 'Description', order => 2, show => 0, }, type => { header => 'Type', order => 3, show => 0, }, duplex => { header => 'Duplex
(Link/Admin)', legend => 'Duplex', order => 4, show => 1, data => 'SELF:col_duplex', }, lastchange => { header => 'Last Change', order => 5, show => 0, data => 'SELF:col_lastchange', }, name => { header => 'Name', order => 6, show => 1, }, speed => { header => 'Speed', order => 7, show => 1, }, mac => { header => 'Port Mac', order => 8, show => 0, }, mtu => { header => 'MTU', order => 9, show => 0 }, vlan => { header => 'Native
VLAN', legend => 'Native VLAN', order => 10, show => 1, }, vmember => { header => 'VLAN
Membership', legend => 'VLAN Membership', order => 11, show => 1, data => 'SELF:col_vmember', noesc => 1, }, connected => { header => sprintf("Connected
Devices%s", $arg_age eq 'on' ? '
(Last Seen)' : ''), legend => 'Connected Devices', order => 12, show => 1, data => 'SELF:col_connected', noesc => 1, }, stp => { header => 'Spanning Tree', order => 13, show => 0, }, up => { header => 'Status', order => 14, show => 0, }, control => { header => 'Port
Control', legend => 'Port Control', order => 15, show => $port_control, data => 'SELF:col_portcontrol', noesc => 1, }, graphs => { header => 'Graphs', order => 16, show => 0, data => $netdisco::CONFIG{col_graphs_data}, }, poe_admin => { header => 'PoE Admin', order => 17, show => 0, data => 'SELF:col_poe_info', }, poe_status => { header => 'PoE Status', order => 18, show => 0, data => 'SELF:col_poe_info', }, poe_class => { header => 'PoE Class', order => 19, show => 0, data => 'SELF:col_poe_info', }, poe_power => { header => 'PoE Power
(in mW)', legend => 'PoE Power', order => 20, show => 0, data => 'SELF:col_poe_info', }, ); my %device_info = ( 'Addresses' => 'addresses', #'First Discovered' => 'creation', #'Last MacSuck' => 'last_macsuck', #'Last ArpNip' => 'last_arpnip', 'Mac Address' => 'mac', #'OSI Layers' => 'layers', 'VTP Domain' => 'vtp_domain', #'Ports' => 'ports', #'Backplane Slots' => 'slots', ); %# %# %# <%init> # Parsing of Arguments $arg_age = $device_age; $arg_arch = $archive; @arg_port = @port; $arg_node_ip = $node_ip; $arg_node_dns = $node_dns; $arg_node_nbt = $node_nbt; $arg_ports = $ports; $arg_timecount = $timecount; $arg_timeunit = $timeunit; # Make sure that only valid time units are passed, reset to "months" if the check fails unless (scalar grep(/^$arg_timeunit$/, @$valid_time_units)) { $arg_timeunit = 'months'; $timeunit = 'months'; } # Make sure that a positive integer is passed as count, reset to "3" if the check fails unless ($arg_timecount =~ m/^\d+$/) { $arg_timecount = 3; $timecount = 3; } if ($ip) { # Save Search Term $match = $ip; # Resolve input my $hostname = &hostname($ip); my $ip = &getip($ip); # Check if we're an alias of another device $devip = &root_device($ip); # redirect to search if no match $m->redirect("device_search.html?text=$match") unless $devip; # Grab Device INFO $device = sql_hash('device', ['ip','extract(epoch from creation) as creation','dns', 'description','uptime','contact','name','location','layers', 'ports','mac','serial','model','ps1_type','ps2_type','ps1_status', 'ps2_status','fan','slots','vendor','log','os_ver','os','vtp_domain', 'extract(epoch from last_discover) as last_discover', 'extract(epoch from last_macsuck) as last_macsuck', 'extract(epoch from last_arpnip) as last_arpnip', 'snmp_class' ], {'ip'=>$devip}); # This could take a while. $m->flush_buffer(); # Grab addresses my $addresses = sql_rows('device_ip',['alias','dns','port','subnet'], {'ip'=>$devip}); # Sort Aliases by Port my $port_addresses = {}; foreach my $a (@$addresses) { push @{$port_addresses->{$a->{port}}},$a; } $device->{addresses} = $addresses; # Hide Ports if ($arg_ports =~ /hide/i) { @port = @arg_port = (); } # Most magic to mark ports as "free" after given time interval ($reftime, $refsql, $freecol) happens here my $reftime = int( $device->{last_discover} - ($device->{uptime} / 100) ) || 0; # We need lastchange/100 but can't use it in the query... later on it will be used in the left hand side # of a comparison in the WHERE-clause. However, sql_query() has a special interpretation for a slash in such a # query component; workaround in this case is to multiply by 0.01 instead of dividing by 100. my $refsql = "age(to_timestamp($reftime + lastchange*0.01))"; my $freecol = "(case when (up<>\'up\' and $refsql > interval \'$arg_timecount $arg_timeunit\') then 1 else 0 end) as free"; # Selected Ports if (scalar @port) { # change default of 'all' foreach my $portreq (@port) { next unless defined $portreq; my $p = sql_rows('device_port', ['*', $freecol], {'ip'=>$devip,'port/name/descr'=>$portreq} ) || []; # add our results to the list if (defined $p and scalar @$p){ $arg_ports = $ports = 'selected'; push (@$db_ports,@$p); } } } # All Ports if ($arg_ports eq 'all') { @arg_port = @port = ('all'); $db_ports = sql_rows('device_port', ['*', $freecol], {'ip'=>$devip} ) || []; } elsif ($arg_ports eq 'free') { @arg_port = @port = ('free'); $db_ports = sql_rows('device_port', ['*', $freecol], { 'ip'=>$devip, 'up'=>\\"<> 'up'", $refsql => \\" > interval \'$arg_timecount $arg_timeunit\'" } ) || []; } # PORTS - Connected Nodes, addresses and log entries foreach my $portreq (@$db_ports) { my $switch = $portreq->{ip}; my $port = $portreq->{port}; $portreq->{portdisp} = $portreq->{port}; # Get count of log entries for this port $portreq->{logs} = sql_scalar('device_port_log',['count(id)'],{'ip'=>$switch,'port'=>$port}); # Get Nodes Attached my $nodes = sql_rows('node', ['mac','active','extract (epoch from time_first) as time_first', 'extract (epoch from time_last) as time_last'], {'switch' => $switch, 'port' => $port } ); $portreq->{macs} = (defined $nodes and scalar @$nodes) ? $nodes : undef; # Get Power info $portreq->{power} = sql_hash('device_port_power',['*'],{'ip'=>$switch,'port'=>$port}); # Get SSIDs my $ssids = sql_rows('device_port_ssid',['*'],{'ip'=>$switch,'port'=>$port}); $portreq->{ssids} = (defined $ssids and scalar @$ssids) ? $ssids : undef; # Get VLANs my $vlans = sql_rows('device_port_vlan',['vlan'], {'ip'=>$switch,'port'=>$port}); my $dev_vlans = sql_rows('device_vlan',['vlan'], {'ip'=>$switch}); if (scalar @$vlans == scalar @$dev_vlans) { $portreq->{vlans} .= 'All'; } elsif (scalar @$vlans != 0) { $portreq->{vlans} .= (join ',', sort {$a <=> $b} map {$_->{'vlan'}} @$vlans); } # Save MAC addresses for IP lookup foreach my $node (@$nodes){ my $mac = $node->{mac}; $node_ips->{$mac}++; $node_nbts->{$mac}++; } # Add addresses to display of port name my $addresses = $port_addresses->{$port} || []; foreach my $alias ( sort {sort_ip($a->{alias},$b->{alias})} @$addresses ) { my $alias_ip = $alias->{alias}; my $s = $alias->{subnet}; my $alias_subnet = defined $s ? "$s" : ''; my $dns = $alias->{dns} || ''; $dns =~ s/\Q$domain\E//; my $alias_ip_anch = 'a_' . $alias_ip; $alias_ip_anch =~ s/\./_/g; $portreq->{portdisp} .= "
+ \n"; $portreq->{portdisp} .= "$alias_ip"; $portreq->{portdisp} .= "$dns $alias_subnet\n"; } } # Get IP addresses of connected nodes if ($node_ip eq 'on'){ my @macs = keys %$node_ips; my $ips = sql_rows('node_ip',['mac','ip'], {active => 1, mac => [\@macs] } ); $node_ips = {}; # Push IP address into list in %node_ips hash foreach my $macip (@$ips){ my $mac = $macip->{mac}; my $ip = $macip->{ip}; push ( @{$node_ips->{$mac}},$ip); } } # Get NetBIOS addresses of connected nodes if ($node_nbt eq 'on'){ my @macs = keys %$node_nbts; my $nbts = sql_rows('node_nbt',['mac','nbname','domain','user','ip'], {active => 1, mac => [\@macs] } ); $node_nbts = {}; # Push IP address into list in %node_nbts hash foreach my $macnbt (@$nbts){ my $mac = $macnbt->{mac}; push ( @{$node_nbts->{$mac}},$macnbt); } } # Get power supply info $device->{poe} = sql_rows('device_power',['*'],{'ip'=>$devip},0,'order by module'); foreach my $poe (@{$device->{poe}}) { $m->comp('SELF:poe_stats', poe => $poe); } # Get modules my $modules = sql_rows('device_module',['*'],{'ip'=>$devip},0,'order by parent,pos,index') || []; foreach my $module (@$modules) { my $m_class = $module->{class}; $modules{$module->{index}}{module} = $module; if ($module->{parent}) { # Next wrong: some things have weird pos' # index | description | type | parent | class | pos #-------+----------------------------------------+---------------------+--------+---------+----- # 1 | Cisco Aironet 1200 Series Access Point | cevChassisAIRAP1210 | 0 | chassis | -1 # 3 | PowerPC405GP Ethernet | cevPortFEIP | 1 | port | -1 # 2 | 802.11G Radio | cevPortUnknown | 1 | port | 0 $module->{pos} = 0 if ($module->{pos} < 0); # this is wrong. a given parent can # have multiple items at a single pos value. # (HP may have gotten this wrong, but that's # reality...) if ($module->{pos}) { ${$modules{$module->{parent}}{children}{$module->{class}}}[$module->{pos}] = $module->{index}; } else { push(@{$modules{$module->{parent}}{children}{$module->{class}}}, $module->{index}); } } else { push(@{$modules{root}}, $module->{index}); } } # Resolve IPs of connected nodes to host names if ($node_ip eq 'on' and $node_dns eq 'on'){ # TODO: Insert code here ? } } # Change the columns of ports shown if (scalar @portcol and join('',@portcol) !~ /^\s*$/) { # Set all to not seen foreach my $key (keys %port_cols){ $port_cols{$key}->{show} = 0; } # show the ones we want foreach my $col (@portcol) { # Check for funny things passed next unless defined ($port_cols{$col}); # Set the passed one as shown $port_cols{$col}->{show} = 1; } } else { foreach my $key (keys %port_cols) { my $config_override = $netdisco::CONFIG{'col_'.$key.'_show'}; if (defined $config_override) { $port_cols{$key}->{show} = $config_override; } } } # Some constants used in the display if (defined $device) { $dns = $device->{dns} || '[No DNS]'; $vendor = $device->{vendor}; $model = $device->{model}; $want_web_link = (defined $web_vendors->{$vendor} or defined $web_models->{$model}); $web_dns = $dns; $web_dns =~ s/\Q$domain\E//; } %# %# END MAIN COMPONENT %# %# %# page_nav() - SHOW ALL / HIDE ALL %# %# <%method page_nav> %# %# port_view() - Prints out the Port View control form %# <%method port_view> %# %# show_device() - Display device Info. %# <%method show_device>

Device Details

% if (defined $device->{fan} or $device->{ps1_status} or (defined $device->{poe} and scalar @{$device->{poe}})) { % } <%perl> # Print out each item in the database that we have using the # %device_info map. foreach my $item (sort keys %device_info) { my $db_col = $device_info{$item}; my $val = $device->{$db_col}; next unless defined $val and length($val); # Munge if ($db_col eq 'addresses'){ next unless scalar @$val; my @vals; foreach my $alias (sort { sort_ip($a->{alias}, $b->{alias}) } @$val){ my $ip = $alias->{alias}; my $d = $alias->{dns}; my $dns = '[No DNS]'; if (defined $d) { $d =~ s/\Q$domain\E//; $dns = "{dns}\">$d" } my $port = $alias->{port}; my $s = $alias->{subnet}; my $subnet = defined $s ? "$s" : ''; push (@vals, "\n"); } $val = "
Name <%$device->{name}|h%>
Location / Contact <%$device->{location} || '[Not Set]' |h%> % if ( $admin ) { [change] % } / <%$device->{contact} || '[Not Set]' |h%>
Model / Serial <%$device->{vendor}%> <%$device->{model}%><% defined $device->{snmp_class} ? ' ('.$device->{snmp_class}.')' :'' |h %> / <%$device->{serial} || 'Unknown'%>
OS / Version <%$device->{os} || 'Unknown'%> / <%$device->{os_ver} || 'Unknown'%>
Description <%$device->{description}|h%>
Timestamps uptime <% $m->comp('SELF:uptime', uptime => $device->{uptime})%>
discover <% scalar localtime($device->{last_discover}) %>
% if (defined $device->{last_arpnip}) { arpnip <% scalar localtime $device->{last_arpnip}%>
% } % if (defined $device->{last_macsuck}) { macsuck <% scalar localtime $device->{last_macsuck}%>
% }
Power % if (defined $device->{fan}) { Fan : <%$device->{fan}%>    % } % if (defined $device->{ps1_status}) { PS1 [<%$device->{ps1_type}%>] : <%$device->{ps1_status}%>   % } % if (defined $device->{ps2_status}) { PS2 [<%$device->{ps2_type}%>] : <%$device->{ps2_status}%>   % } % if (defined $device->{poe} and scalar @{$device->{poe}}) { % foreach my $poe (@{$device->{poe}}) {
POE module <%$poe->{module}%> : <%$poe->{status}%>, <%$poe->{stats}->{ports}%> power-capable ports, <%$poe->{stats}->{on}%> powered (<%$poe->{stats}->{disabled}%> admin disabled, <%$poe->{stats}->{err}%> errors), <%$poe->{stats}->{committed}%>/<%$poe->{power}%> watts committed. % } % }
$ip$dns$port$subnet
\n"; $val .= join("",@vals); $val .= "
\n"; } if ($db_col eq 'creation') { $val = localtime($val); } if ($db_col eq 'last_discover') { $val = localtime($val); } if ($db_col eq 'last_macsuck') { $val = localtime($val); } if ($db_col eq 'last_arpnip') { $val = localtime($val); } my $match_class = ++$odd % 2; $m->out("$item"); $m->out("$val\n"); } # Treat the log a little different my $log = $device->{log}; if (defined $log and length($log)){ my $logclass = ++$odd % 2; Log %} <& SELF:page_nav &> %# %# show_module() - Display device modules. %# <%method show_module>

Device Modules

<& SELF:page_nav &> %# %# dump_module() - Create device module list. %# <%method dump_module> <%args> $id
  • <%perl> return if ($id eq 'root'); if (!defined($modules{$id})) { print "can't get module $id\n"; return; } my $mod = $modules{$id}{module}; <% $mod->{description} %> % if ($mod->{name}) { (<% $mod->{name} %>) % } % if ($mod->{port}) { (<% $mod->{port} %>) % } % for my $f qw(fw hw sw) { % if ($mod->{"${f}_ver"}) { [<%$f%>: <%$mod->{"${f}_ver"}%>] % } % } % if ($mod->{serial}) { [serial: <%$mod->{serial}%>] % } % if ($mod->{type}) { / <% $mod->{type} %> % } % if ($mod->{model}) { / <% $mod->{model} %> % } % if ($mod->{fru}) { [FRU] % } %# // <% $mod->{class} %> % if ($modules{$id}{children}) { % }
  • %# %# port_header() - Prints out the header block depending on the columns selected %# <%method port_header> % foreach my $col (sort {$port_cols{$a}->{order} <=> $port_cols{$b}->{order}} keys %port_cols){ % my $desc = $port_cols{$col}->{header}; % my $on = $port_cols{$col}->{show}; % next unless $on; <% $desc %> %} %# %# show_ports() %# <%method show_ports> % # Return if there are no matches % unless (scalar @$db_ports) { % # add these two layers so we can still view them even if there are no ports. <& SELF:port_key &> <& SELF:port_view &> % return; } % # Have matches, will travel. <& SELF:port_header &> <%perl> # Display the Ports foreach my $port (sort sort_port @$db_ports){ my $remote_ip = $port->{remote_ip}; my $remote_type = $port->{remote_type}; my $up_admin = $port->{up_admin} || ''; my $stp = $port->{stp} || ''; my $up = $port->{up} || ''; # An uplink is a port that has a remote_ip but is not a phone # We do _not_ allow shutdown of ports that have remote info but are not # in our database. Consider an SNMP problem. Or consider your routes off-site # where your ISP might squawk CDP, but we don't have SNMP. We don't want to # allow people to turn those off. my $is_uplink = (defined $remote_ip and !(defined $remote_type and $remote_type =~ /ip.phone/i)) ? 1 : 0; my $class = ($up eq 'down' or $up eq 'notPresent') ? 'port-down' : 'port-up'; $class = $port->{free} ? 'port-free' : $class; $class = $up_admin eq 'down' ? 'port-off' : $class; # Check for STP blocking, but not down $class = ($up ne 'down' and $stp =~ /(blocking|broken)/) ? 'port-block' : $class; my $rowclass = (++$odd % 2 ) ? 'ports-0': 'ports-1'; <%perl> foreach my $col (sort {$port_cols{$a}->{order} <=> $port_cols{$b}->{order}} keys %port_cols){ my $colcheck = $port_cols{$col}->{show}; next unless $colcheck; my $val; my $coldata = $port_cols{$col}->{data}; # Coldata can be coderef to execute or scalar for Mason component if (defined $coldata) { my $reftype = ref($coldata); if ($reftype) { if ($reftype eq 'CODE') { # Execute coderef with device hash, port hash and key name as arguments $val = &$coldata($device, $port, $col); } else { # other ref not implemented $val = $reftype . ' ref not implemented'; } } elsif (ref(\$coldata) eq 'SCALAR') { # value passed is scalar -> see if it's a Mason component & try to call it if ( $m->comp_exists($coldata) ) { if ($port_cols{$col}->{noesc} || $netdisco::CONFIG{'col_'.$col.'_noesc'} ) { # "noesc" property on a Mason component: let the component provide its own output. $val = $m->scomp($coldata, dev => $device, port => $port, col => $col); } else { # Without "noesc" property, we'll just use the return val. $val = $m->comp($coldata, dev => $device, port => $port, col => $col); } } else { # Not a component? Shouldn't happen; print the name in the column for debugging. $val = sprintf("[%s] is not a Mason component", $coldata); } } else { # Value passed was not a ref and not a scalar $val = 'Don\'t know how to handle this...'; } } else { # no "data" property given for column -> display contents of DB col $val = $port->{$col}; } % } # end foreach col % } # end foreach port % # Print out the legend again if we have lots of results % $m->comp('SELF:port_header') if (scalar @$db_ports > 10); %
    \ % if (defined $val) { % if ( $port_cols{$col}->{noesc} || $netdisco::CONFIG{'col_'.$col.'_noesc'} ) { <% $val %> \ % } else { <% $val |h %> \ % } % } else {   % }
    % $m->comp('SELF:page_nav') if (scalar @$db_ports > 10); <& SELF:port_key &> <& SELF:port_view &> %# %# port_key() - Shows the port_key table, located in hidden div port_key %# <%method port_key> %# %# col_lastchange() - determines the actual timestamp of "last change" for a port %# <%method col_lastchange> <%args> $dev $port <%perl> my $diff_sec = ($dev->{uptime} - $port->{lastchange}) / 100; return scalar localtime($dev->{last_discover} - $diff_sec); %# %# col_duplex() - pretty print link/admin duplex settings for a port %# <%method col_duplex> <%args> $dev $port <%perl> my $duplex_oper = $port->{duplex} || '[NA]'; my $duplex_admin = $port->{duplex_admin} || '[NA]'; return sprintf("%s/%s", $duplex_oper, $duplex_admin); %# %# col_poe_info() - Return the PoE Admin status, Oper status, or Class %# <%method col_poe_info> <%args> $dev $port $col <%perl> my $power = $port->{power}; $col =~ s/^poe_//; return $power->{$col}; %# %# col_vmember() - pretty print all VLANs allowed on a port %# <%method col_vmember> <%args> $dev $port <%perl> my $vlan_ids = $port->{vlans} || ''; # munging any col with HTML is done after escaping... HTML::Mason::Escapes::html_entities_escape( \$vlan_ids ); # vlan col needs wrapping with
    $vlan_ids =~ s/(\d+,\d+,\d+,)/$1
    /g; $vlan_ids =~ s{(\d+)}{$1}g; if (defined $vlan_ids) { <% $vlan_ids %> \ % } else {   \ % } %# %# col_portcontrol() - pretty print the icons in the portcontrol column %# <%method col_portcontrol> <%args> $dev $port % my $is_uplink = ( defined $port->{remote_ip} and !(defined $port->{remote_type} and $port->{remote_type} =~ /ip.phone/i) ) ? 1 : 0; % if ($dev->{dns} =~ /^hub/i and $port_info) { Pinnacles DB Info \ % } % if ($port->{logs}){ <%$port->{logs}%> Admin Log Entries \ % } % if ($port_control and !$is_uplink) { % my $dir = $port->{up_admin} eq 'down' ? 'up' : 'down'; Bring Port <%$dir%> \ % if ($vlan_ctl) { \ Change VLANs \ % } % } elsif (! $port->{logs}) {   \ % } %# %# col_connected() - the magic to display conncted nodes & devices %# <%method col_connected> <%args> $dev $port <%perl> # CDP speaking device connected my $remote_ip = $port->{remote_ip}; my $remote_id = $port->{remote_id}; my $remote_port = $port->{remote_port}; my $remote_type = $port->{remote_type}; if (defined $remote_ip) { my $name = ''; my $link = ''; my $remote_dev = sql_hash('device',['ip','dns'], {'ip'=>$remote_ip}); my $alias = sql_hash('device_ip',['ip','dns'], {'alias'=>$remote_ip}); # Resolve IP address squawked to root device if (defined $alias) { $remote_ip = $alias->{ip}; $name = $alias->{dns}; $name = defined $name ? $name : $remote_ip; $name =~ s/\Q$domain\E//; $name .= " ($remote_port)"; $name = "$name"; $link = "device.html?ip=$remote_ip&port=$remote_port"; # Not an alias, use info from device table } elsif (defined $remote_dev) { $name = $remote_dev->{'dns'}; $name = defined $name ? $name : $remote_ip; $name =~ s/\Q$domain\E//; $name .= " ($remote_port)"; $name = "$name"; $link = "device.html?ip=$remote_ip&port=$remote_port"; # Found a device, but not in our database } else { if ($arg_node_dns eq 'on') { $name = hostname($remote_ip) || $remote_ip; $name =~ s/\Q$domain\E//; } else { $name = $remote_ip; } my $spanclass = (defined $remote_type and $remote_type =~ /ip.phone/i) ? 'ip-phone' : 'dead-link'; $name = "$name"; $name .= " ($remote_port)"; $name .= "
       ($remote_type)" if defined $remote_type; $name .= "/($remote_id)" if defined $remote_id; $link = "node.html?node=$remote_ip"; } <%$name%> \ <%perl> } # Show SSIDs my $portssids = $port->{ssids} || []; my $ssidbr = defined($remote_ip); foreach my $ssid (@$portssids) { my $id = $ssid->{ssid}; my $bcast = $ssid->{broadcast} ? "(B)" : ""; $m->out("
    \n") if $ssidbr; $ssidbr = 1; SSID: <%$id%> <%$bcast%> <%perl> } # Show connected nodes my $seen_macs=0; my $portnodes = $port->{macs} || []; foreach my $node (sort {$a->{mac} cmp $b->{mac}} @$portnodes) { my $mac = $node->{mac}; my $active = $node->{active}; my $time_last = $node->{time_last}; # Connected Device Age Stamp? my $age = $now - $time_last; $age = sprintf("%d", ($age / (60*60*24))); my $show_age = ($arg_age eq 'on' and $age > 0) ? " ($age days)" : ''; # Show Archived Data? next unless ($active or $arg_arch eq 'on'); $m->out("
    \n") if ((defined $remote_ip or @$portssids) and $seen_macs == 0); $seen_macs++; <% $mac%><%$show_age%><% $active ? '' : '*'%>
    <%perl> # Show node_ips? if ($arg_node_ip eq 'on' and defined $node_ips->{$mac}) { foreach my $ip (sort sort_ip @{$node_ips->{$mac}}) { # Show Node DNS ? my $host = $ip; if ($arg_node_dns eq 'on'){ $host = hostname($ip) || $ip; $host =~ s/\Q$domain\E//; # Add IP if we found a hostname. $host .= " ($ip)" if ($host ne $ip); }      <%$host%>
    <%perl> } # /each node_ip } # /if node_ip # Show node_nbts? if ($arg_node_nbt eq 'on' and defined $node_nbts->{$mac}) { foreach my $nbt (sort @{$node_nbts->{$mac}}) {      \\<%$nbt->{domain}%>\<%$nbt->{nbname}%>
         <%$nbt->{nbuser} || '[No User]'%>@<%$nbt->{ip}|h%>
    <%perl> } # /each node_nbt } # /if node_nbt } # /each node # Place holder for no connected devices unless ($seen_macs or defined $remote_ip) { $m->out(' '); } # end connected dev col. %# %# uptime() - Returns pretty-print of uptime values %# <%method uptime> <%args> $uptime <%perl> # uptime is in 100ths of seconds my $val = int($uptime/100); my $sec = $val % 60; $val = ( $val - $sec ) / 60; my $min = $val % 60; $val = ( $val - $min ) / 60; my $hour = $val % 24; $val = ( $val - $hour ) / 24; my $day = $val % 7; my $week = ($val - $day) / 7; my @times; push (@times,"$week weeks") if $week; push (@times,"$day days") if ($week or $day); push (@times,"$hour hours") if ($week or $day or $hour); push (@times,"$min min.") if ($week or $day or $hour or $min); push (@times,"$sec sec.") unless ($week or $day or $hour or $min); return join(',',@times); %# %# poe_stats() - Return the aggregate Power-over-ethernet information for this device. %# <%method poe_stats> <%args> $poe <%perl> my $poemax = { 'class0' => 12.95, 'class1' => '3.84', 'class2' => 6.49, 'class3' => 12.95 }; $poe->{stats} = { 'disabled' => 0, 'ports' => 0, 'on' => 0, 'err' => 0, 'committed' => 0, 'estimated' => 0, 'measured' => 0 }; my $poeports = sql_rows('device_port_power',['*'],{'ip'=>$poe->{ip},'module'=>$poe->{module}}); foreach my $pport (@{$poeports}) { $poe->{stats}->{ports}++; if ($pport->{admin} eq 'false') { $poe->{stats}->{disabled}++; } else { if ($pport->{status} ne 'searching' and $pport->{status} ne 'deliveringPower') { $poe->{stats}->{err}++; } elsif ($pport->{status} eq 'deliveringPower') { $poe->{stats}->{on}++; if (defined $pport->{power}) { $poe->{stats}->{committed} += int($pport->{power}/1000); $poe->{stats}->{measured}++; } else { $poe->{stats}->{committed} += $poemax->{$pport->{class}}; $poe->{stats}->{estimated}++; } } } } %# %# Add javascript routines to header %# tl(layer) - Toggles Layer visibility %# tlgo(layer,[anchor]) - Toggles layer and goes to anchor, %# default anchor is same as layer %# <%method html_head> <%method title> - Device View \ %# $Id: device.html,v 1.62 2011/03/31 10:28:44 olly_g Exp $ %# vim:syntax=mason