#!/usr/bin/perl =for commnet Part of BBHN Mesh -- Used for creating Amateur Radio friendly mesh networks Copyright (C) 2015 Conrad Lara See Contributors file for additional contributors Copyright (c) 2013 David Rivenburg et al. BroadBand-HamNet This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation version 3 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . =cut $debug = 0; BEGIN {push @INC, '/www/cgi-bin'}; use perlfunc; # collect some variables $node = nvram_get("node"); $node = "NOCALL" if $node eq ""; $tactical = nvram_get("tactical"); $config = nvram_get("config"); $config = "not set" if $config eq "" or not -d "/etc/config.$config"; ($my_ip) = get_ip4_network("wlan0"); read_postdata(); system "mkdir -p /tmp/web"; system "touch /tmp/web/automesh" if $parms{auto}; system "rm -f /tmp/web/automesh" if $parms{stop}; # parse the txtinfo output $table = "none"; chomp($tmperr = `mktemp /tmp/web/nc.XXXXXX`); foreach(`echo /all | nc 127.0.0.1 2006 2>$tmperr`) { if(/^Table: (\w+)/) { $table = $1; next; } next if /^\s*$/ or /^\D/; if($table eq "Links") { ($junk, $ip, $junk, $lq) = split /\s+/, $_; $links{$ip} = $lq; } elsif($table eq "Neighbors") { } elsif($table eq "Topology") { } elsif($table eq "HNA") { } elsif($table eq "MID") { } elsif($table eq "Routes") { ($ip, $junk, $junk, $etx) = split /\s+/, $_; ($net, $cidr) = split /\//, $ip; $routes{$net}{cidr} = $cidr; $routes{$net}{etx} = $etx; $routes{$net}{value} = ip2decimal($net); $routes{$net}{mask} = 0xffffffff - ((1 << (32 - $cidr)) - 1); } } # stat and -s do not work in microperl @parts = split /\s+/, `ls -l $tmperr`; $txtinfo_err = $parts[4]; unlink $tmperr; # load the local hosts file foreach(`cat /etc/hosts`) { next unless /^10[.]/; chomp; ($ip, $name, $tactical) = split /\s+/, $_; next if $name =~ /^(localhost|localnode|localap|dtdlink\..*)$/; if($ip eq $my_ip) { $tactical = "" unless $tactical; $localhosts{$ip}{tactical} = $tactical; $localhosts{$ip}{name} = $name; } else { push @{$localhosts{$my_ip}{hosts}}, $name; } } # load the olsr hosts file foreach(`cat /var/run/hosts_olsr 2>/dev/null`) { next unless /^\d/; chomp; ($ip, $name, $junk, $originator, $mid, $midnum) = split /\s+/, $_; next unless $originator; next if $originator eq "myself"; if ( $name =~ /^dtdlink\..*$/ ) { $hosts{$ip}{name} = $name; next; } if(defined $mid and $midnum =~ /^\#(\d+)/) { if ( !exists $hosts{$ip}{name} ) { $hosts{$ip}{name} = $name; } $hosts{$ip}{hide} = 1; $hosts{$originator}{mid} = $1; } elsif($ip eq $originator) { if($hosts{$ip}{name}) { $hosts{$ip}{tactical} = $name } else { $hosts{$ip}{name} = $name } } else { push @{$hosts{$originator}{hosts}}, $name; } } # load the olsr services file foreach(`cat /var/run/services_olsr 2>/dev/null`) { next unless /^\w/; chomp; ($url, $junk, $name) = split /\|/, $_; next unless defined $name; ($host, $port) = $url =~ /^\w+:\/\/([\w\-\.]+):(\d+)/; ($name, $originator) = split /\#/, $name; $name =~ s/\s+$//; #$host = $originator eq " my own service" ? $node : $hosts{$originator}{name}; # attempt to work around olsr never forgetting defunct services # assume that the first entry in the file by this name is the most recent, ignore the rest next if $services{$host}{$name}; $services{$host}{$name} = $port ? "$name" : $name; } # load the node history foreach(`cat /tmp/node.history 2>/dev/null`) { chomp; ($ip, $age, $host) = split / /, $_; next unless $age; $host = "" unless $host; $host =~ s|/| / |; $history{$ip}{age} = $age; $history{$ip}{host} = $host; } #delete $hosts{"127.0.0.1"}; # generate the page http_header(); html_header("$node mesh status", 0); print "\n" if -f "/tmp/web/automesh"; print "\n"; print "
\n"; print "\n"; print "
\n"; alert_banner(); # page header print "

$node mesh status


"; # nav buttons if(-f "/tmp/web/automesh") { print "\n"; } elsif($config eq "mesh") { print "\n"; print "   \n"; print "\n"; } print "   "; print "\n"; if($config ne "mesh") { print "

This page is available only when the router is acting as a Mesh Node.\n"; print "
\n"; exit; } elsif($txtinfo_err) { print "

Whoops! OLSR is not running, try again later.\n"; print "\n"; exit; } print "


\n"; unless(keys %localhosts or keys %links) { print "No other nodes are available.\n"; print "\n"; # show local hosts print "\n"; print "\n"; if(keys %localhosts) { %rows = (); foreach $ip (keys %localhosts) { $host = $localhosts{$ip}{name}; $tactical = $localhosts{$ip}{tactical} ? " / " . $localhosts{$ip}{tactical} : ""; $rows{$host} = sprintf "\n"; # add locally advertised dmz hosts foreach $dmzhost (@{$localhosts{$ip}{hosts}}) { $rows{$host} .= ""; $rows{$host} .= "\n"; } } foreach(sort keys %rows) { print $rows{$_} } } else { print "\n"; } # show remote nodes print "\n"; print "\n"; print "\n"; %rows = (); foreach $ip (keys %hosts) { next if $links{$ip}; next if exists $hosts{$ip}{hide}; $host = $hosts{$ip}{name}; $tactical = $hosts{$ip}{tactical} ? " / " . $hosts{$ip}{tactical} : ""; $etx = "unknown"; if($routes{$ip}) # get the etx directly { $etx = sprintf "%.2f", $routes{$ip}{etx}; } else # find the subnet it belongs to { foreach $net (keys %routes) { next unless (ip2decimal($ip) & $routes{$net}{mask}) == $routes{$net}{value}; $etx = sprintf "%.2f", $routes{$net}{etx}; last; } } next if $etx eq "unknown"; $rows{$host} = sprintf "\n"; # add advertised dmz hosts foreach $dmzhost (@{$hosts{$ip}{hosts}}) { $rows{$host} .= ""; $rows{$host} .= "\n"; } } if(keys %rows) { foreach(sort keys %rows) { print $rows{$_} } } else { print "\n"; } print "
Local HostsServices

%s \n", $host . $tactical; foreach(sort keys %{$services{$host}}) { $rows{$host} .= "" . $services{$host}{$_} . "
\n"; } $rows{$host} .= "
 $dmzhost\n"; foreach(sort keys %{$services{$dmzhost}}) { $rows{$host} .= "" . $services{$dmzhost}{$_} . "
\n"; } $rows{$host} .= "
none
 
Remote Nodes  ETX  Services

%s", $host, $host . $tactical; if($midnum = $hosts{$ip}{mid}) # show mid interfaces { $midnum = ($midnum > 1) ? "*$midnum" : ""; $rows{$host} .= "   (mid$midnum)"; } $rows{$host} .= sprintf "%s\n", $etx; foreach(sort keys %{$services{$host}}) { $rows{$host} .= "" . $services{$host}{$_} . "
\n"; } $rows{$host} .= "
 $dmzhost\n"; foreach(sort keys %{$services{$dmzhost}}) { $rows{$host} .= "" . $services{$dmzhost}{$_} . "
\n"; } $rows{$host} .= "
none
 \n"; # show current neighbors print "\n"; print "\n"; if(keys %links) { %rows = (); foreach $ip (keys %links) { $host = $hosts{$ip}{name} ? $hosts{$ip}{name} : $ip; $tactical = $hosts{$ip}{tactical} ? " / " . $hosts{$ip}{tactical} : ""; $rows{$host} = sprintf "\n"; # add advertised dmz hosts foreach $dmzhost (@{$hosts{$ip}{hosts}}) { $rows{$host} .= "\n"; } } foreach(sort keys %rows) { print $rows{$_} } } else { print "\n"; } # show previous neighbors print "\n"; print "\n"; print "\n"; %rows = (); ($uptime) = `cat /proc/uptime` =~ /^(\d+)/; foreach $ip (keys %history) { next if $links{$ip}; $age = sprintf "%010d", $uptime - $history{$ip}{age}; $host = $history{$ip}{host} ? $history{$ip}{host} : $ip; $rows{$age} .= sprintf "\n"; } if(keys %rows) { foreach(sort keys %rows) { print $rows{$_} } } else { print "\n"; } print "
Current Neighbors  LQ  Services

%s", $host, $host . $tactical; if($midnum = $hosts{$ip}{mid}) # show mid interfaces { $midnum = ($midnum > 1) ? "*$midnum" : ""; $rows{$host} .= "   (mid$midnum)"; } $rows{$host} .= sprintf "%.0f%%\n", 100*$links{$ip}; foreach(sort keys %{$services{$host}}) { $rows{$host} .= "" . $services{$host}{$_} . "
\n" } $rows{$host} .= "
 $dmzhost\n"; foreach(sort keys %{$services{$dmzhost}}) { $rows{$host} .= $services{$dmzhost}{$_} . "
\n" } $rows{$host} .= "
none
 
Previous NeighborsWhen

%s", $host; foreach(@{$hosts{$ip}{hosts}}) { $rows{$age} .= "
$_" } $rows{$age} .= "
"; if($age < 3600) { $val = int($age/60); $rows{$age} .= $val == 1 ? "1 minute ago" : "$val minutes ago"; } else { $val = sprintf "%.1f", $age/3660; $rows{$age} .= $val eq "1.0" ? "1 hour ago" : "$val hours ago"; } $rows{$age} .= "
none
\n"; # end print "\n"; print "\n"; if($debug) { print "
\n";
    print "localhosts\n";
    foreach $ip (sort keys %localhosts)
    {
	printf "%s %s", $ip, $localhosts{$ip}{name};
	printf "/%s", $localhosts{$ip}{tactical} if $localhosts{$ip}{tactical};
	foreach(@{$localhosts{$ip}{hosts}}) { print ":$_" }
	print "\n";
    }

    print "\nhosts\n";
    foreach $ip (sort keys %hosts)
    {
	$hosts{$ip}{name} = "" unless $hosts{$ip}{name};
	printf "%s %s", $ip, $hosts{$ip}{name};
	printf "/%s", $hosts{$ip}{tactical} if $hosts{$ip}{tactical};
	foreach(@{$hosts{$ip}{hosts}}) { print ":$_" }
	printf(" %d", $hosts{$ip}{mid}) if $hosts{$ip}{mid};
	print "\n";
    }    

    print "\nlinks\n";
    foreach(sort keys %links)
    {
	print "$_\n";
    }    

    print "
\n"; } show_debug_info(); show_parse_errors(); print "\n"; print "\n";