"; while(FALSE!==($f=readdir($d))) { if (substr($f,-4)!=".dat") continue; echo "
  • $f\n"; } exit; } if (!file_exists("output/$host.dat")) { echo "No data"; exit; } function parse_dat($path) { $f=fopen($path,"r"); while($l=fgets($f)) { $arg=explode(" ",trim($l)); switch ($arg[0]) { case 'dest': $dest=$arg[1]; break; case 'date': $time=$arg[1]; break; case 'host': if ($arg[2] == "?") $arg[2] = "Unknown"; $host[$arg[1]]=array( 'as' => $arg[2], 'host' => $arg[3], 'ip' => $arg[4], ); break; case 'hop': $hop[$arg[1]][]=$arg[2]; $revhop[$arg[2]][]=$arg[1]; break; case 'star': $star[$arg[1]]=array(); break; default: echo "eh?"; print_r($arg); break; } } return array($host,$hop,$revhop,$star); } $announced=array(); function colour($as) { while (substr($as,0,1)>="A" && substr($as,0,1)<="Z") { $as=substr($as,1); } $as=(int)$as; if ($as==0) return array(255,255,255); $col=array(0,0,0); for($i=0;$i<8;++$i) { for($j=0;$j<3;++$j) { $col[$j]=($col[$j]<<1)|($as&1); $as=$as>>1; } } return $col; } function fore_color($col) { list($r,$g,$b)=$col; $y = $r*.299+$g*.587+$b*.144; if ($y<128) return array(255,255,255); return array(0,0,0); } function get_asname($as) { global $db; while (substr($as,0,1)>="A" && substr($as,0,1)<="Z") { $as=substr($as,1); } $as=(int)$as; if ($as == 0) return "Unknown"; $ret=$db->query("SELECT * FROM asnames WHERE asnum=?",$as); $ret=$ret->fetchrow(DB_FETCHMODE_ASSOC); if ($ret) return $ret["name"]; return "AS$as"; } function make_closed_label($as) { global $openas,$announced; $dot=""; if (!array_key_exists($as,$announced)) { array_push($openas,$as); $col=colour($as); $fcol=fore_color($col); $dot.=" ".$as." [label=\"".get_asname($as)."\", URL=\"?openas=".implode($openas,",")."\",fill color=\"#".sprintf("%02x%02x%02x",$col[0],$col[1],$col[2])."\",style=\"filled\",fontcolor=\"#".sprintf("%02x%02x%02x",$fcol[0],$fcol[1],$fcol[2])."\",shape=\"record\",height=\".01\"];\n"; array_pop($openas); } return array($dot,$as); } function make_open_label($node,$as,$label,$fillcolour,$fontcolour,$circle=0) { global $announced,$openas; if (array_key_exists($node,$announced)) return array("",$node); $dot=" subgraph cluster_".$as." {\n"; $col=colour($as); $fcol=fore_color($col); $URL="?openas=".implode(array_diff($openas,array($as)),","); $dot.=" [label = \"".get_asname($as)."\",fillcolor=\"#".sprintf("%02x%02x%02x",$col[0],$col[1],$col[2])."\",style=\"filled\",fontcolor=\"#".sprintf("%02x%02x%02x",$fcol[0],$fcol[1],$fcol[2])."\",URL=\"$URL\"];\n"; $dot.=" $node [ label=\"$label\",fillcolor=\"$fillcolour\",style=\"filled\",fontcolor=\"$fontcolour\""; if (!$circle) $dot.=",shape=\"record\",height=\".01\""; $dot.="];\n"; $dot.=" };\n"; return array($dot,$node); } function make_label($node) { global $host,$hop,$star,$announced,$openas; $dot=""; if (array_key_exists($node,$star)) { /* If this is a "free floating" as, just draw it. */ if (!array_key_exists("as",$star[$node])) { $dot .= " $node [label=\"*\",style=\"filled\",fillcolor=\"#888888\",fontcolor=\"#ff0000\"];\n"; return array($dot,$node); } /* If it's closed, just draw the AS as normal */ if (!in_array($star[$node]["as"],$openas)) { return make_closed_label($star[$node]["as"]); } /* It's an * within an open AS */ return make_open_label($node,$star[$node]["as"], "*","#888888","#FF0000",1); } else if ($node == "?" || substr($host[$node]["as"],0,3)=="RFC") { if (!array_key_exists($node,$announced)) { $dot.=" $node [label=\"".$host[$node]["ip"]."\"];\n"; } return array($dot,$node); } else if (in_array($host[$node]["as"],$openas)) { return make_open_label($node,$host[$node]["as"], $host[$node]["host"],"#FFFFFF","#000000"); } else { return make_closed_label($host[$node]["as"]); } } function make_dot($host,$hop,$star) { global $openas; $dot="digraph traceroute {\n"; $link=array(); $announced=array(); foreach($hop as $fromhost=>$tohosts) { foreach($tohosts as $tohost) { list($dotextra1,$fromas) = make_label($fromhost); list($dotextra2,$toas) = make_label($tohost); if ($fromas == $toas && !in_array($fromas,$openas)) { /* If the AS is closed, and it's an internal link */ continue; } else { $dot.=$dotextra1.$dotextra2; $announced[$fromas]=1; $announced[$toas]=1; if (!array_key_exists($fromas,$link) || !array_key_exists($toas,$link[$fromas])) { $dot.=" $fromas -> $toas;\n"; $link[$fromas][$toas]=1; } } } } $dot.="}\n"; return $dot; } /* Finds the best AS that this node is probably in, given that it's probably * either a "*" or RFC1918 which don't have an explicit AS. * * It does it by walking backwards until it finds a node with an AS, saving * as's as it goes. This function updates this nodes AS (if one is found), * and perhaps a few other AS's for caching purporses. */ function find_best_as($node) { global $star,$host,$revhop,$hop; if (array_key_exists($node,$host) &&array_key_exists("as",$host[$node])) { if ($host[$node]["as"]!="RFC1918") return $host[$node]["as"]; } if (array_key_exists($node,$star) &&array_key_exists("as",$star[$node])) return $star[$node]["as"]; if (array_key_exists($node,$revhop)) { $as=find_best_as($revhop[$node][0]); if ($as=="") { } else if (array_key_exists($node,$host)) $host[$node]["as"]=$as; else if (array_key_exists($node,$star)) $star[$node]["as"]=$as; return $as; } return ""; } list($host,$hop,$revhop,$star)=parse_dat("output/$host.dat"); /* Ok, now I need to figure out what AS's RFC1918 and *'s are in */ foreach($star as $node=>$data) { find_best_as($node); } /* And do all the hosts for good luck too to catch the RFC1918 hosts*/ foreach($host as $node=>$data) { find_best_as($node); } $dot= make_dot($host,$hop,$star); if ($_REQUEST["format"]=="dot") { echo "
    $dot";
    	exit;
    }
    
    $f=fopen("/tmp/foo.dot","w");
    fwrite($f,$dot);
    fclose($f);
    
    switch ($_REQUEST["format"]) {
     case "png":
    	header("Content-type: image/png");
    	passthru("dot -Tpng /tmp/foo.dot");
    	//unlink("/tmp/foo.dot");
    	break;
     case "dot":
     	echo "Dot:";
     	echo $dot;
    	break;
     default:
    ?>