cfgmaker.cisco
上传用户:shbosideng
上传日期:2013-05-04
资源大小:1555k
文件大小:19k
源码类别:

SNMP编程

开发平台:

C/C++

  1. #! /pkg/gnu/bin/perl
  2. # -*- mode: Perl -*-
  3. ##################################################################
  4. # MRTG 2.7.2  -- Config file creator
  5. ##################################################################
  6. # Created by Tobias Oetiker <oetiker@ee.ethz.ch>
  7. # this produces a config file for one router, by bulling info
  8. # off the router via snmp
  9. #################################################################
  10. #
  11. # Distributed under the GNU copyleft
  12. use BER "0.57";
  13. use SNMP_Session "0.59";
  14. use SNMP_util "0.57";
  15. use Socket;
  16. use strict;
  17. use vars '$DEBUG';
  18. my $DEBUG = 0;
  19. my ($session, %ipaddr, %iphost);
  20. sub main {
  21.     snmpmapOID('ipAdEntAddr' => '1.3.6.1.2.1.4.20.1.1',
  22.        'ipAdEntIfIndex' => '1.3.6.1.2.1.4.20.1.2',
  23.        'sysObjectID' => '1.3.6.1.2.1.1.2.0',
  24.        'CiscolocIfDescr' => '1.3.6.1.4.1.9.2.2.1.1.28',
  25.        'ifAlias' => '1.3.6.1.2.1.31.1.1.1.18');
  26.   my(%ifType_d)=('1'=>'Other',
  27.  '2'=>'regular1822',
  28.  '3'=>'hdh1822',
  29.  '4'=>'ddnX25',
  30.  '5'=>'rfc877x25',
  31.  '6'=>'ethernetCsmacd',
  32.  '7'=>'iso88023Csmacd',
  33.  '8'=>'iso88024TokenBus',
  34.  '9'=>'iso88025TokenRing',
  35.  '10'=>'iso88026Man',
  36.  '11'=>'starLan',
  37.  '12'=>'proteon10Mbit',
  38.  '13'=>'proteon80Mbit',
  39.  '14'=>'hyperchannel',
  40.  '15'=>'fddi',
  41.  '16'=>'lapb',
  42.  '17'=>'sdlc',
  43.  '18'=>'ds1',
  44.  '19'=>'e1',
  45.  '20'=>'basicISDN',
  46.  '21'=>'primaryISDN',
  47.  '22'=>'propPointToPointSerial',
  48.  '23'=>'ppp',
  49.  '24'=>'softwareLoopback',
  50.  '25'=>'eon',
  51.  '26'=>'ethernet-3Mbit',
  52.  '27'=>'nsip',
  53.  '28'=>'slip',
  54.  '29'=>'ultra',
  55.  '30'=>'ds3',
  56.  '31'=>'sip',
  57.  '32'=>'frame-relay',
  58.  '33'=>'rs232',
  59.  '34'=>'para',
  60.  '35'=>'arcnet',
  61.  '36'=>'arcnetPlus',
  62.  '37'=>'atm',
  63.  '38'=>'miox25',
  64.  '39'=>'sonet',
  65.  '40'=>'x25ple',
  66.  '41'=>'iso88022llc',
  67.  '42'=>'localTalk',
  68.  '43'=>'smdsDxi',
  69.  '44'=>'frameRelayService',
  70.  '45'=>'v35',
  71.  '46'=>'hssi',
  72.  '47'=>'hippi',
  73.  '48'=>'modem',
  74.  '49'=>'aal5',
  75.  '50'=>'sonetPath',
  76.  '51'=>'sonetVT',
  77.  '52'=>'smdsIcip',
  78.  '53'=>'propVirtual',
  79.  '54'=>'propMultiplexor',
  80.  '55'=>'100BaseVG',
  81.                  #### New IF Types added 9/24/98 by Russ Carleton (roccor@livenetworking.com)
  82.                  #### based on the IANA file updated at ftp://ftp.isi.edu/mib/ianaiftype.mib
  83.                  '56'=>'Fibre Channel',
  84.                  '57'=>'HIPPI Interface',
  85.                  '58'=>'Obsolete for FrameRelay',
  86.                  '59'=>'ATM Emulation of 802.3 LAN',
  87.                  '60'=>'ATM Emulation of 802.5 LAN',
  88.                  '61'=>'ATM Emulation of a Circuit',
  89.                  '62'=>'FastEthernet (100BaseT)',
  90.                  '63'=>'ISDN & X.25',
  91.                  '64'=>'CCITT V.11/X.21',
  92.                  '65'=>'CCITT V.36',
  93.                  '66'=>'CCITT G703 at 64Kbps',
  94.                  '67'=>'Obsolete G702 see DS1-MIB',
  95.                  '68'=>'SNA QLLC',
  96.                  '69'=>'Full Duplex Fast Ethernet (100BaseFX)',
  97.                  '70'=>'Channel',
  98.                  '71'=>'Radio Spread Spectrum (802.11)',
  99.                  '72'=>'IBM System 360/370 OEMI Channel',
  100.                  '73'=>'IBM Enterprise Systems Connection',
  101.                  '74'=>'Data Link Switching',
  102.                  '75'=>'ISDN S/T Interface',
  103.                  '76'=>'ISDN U Interface',
  104.                  '77'=>'Link Access Protocol D (LAPD)',
  105.                  '78'=>'IP Switching Opjects',
  106.                  '79'=>'Remote Source Route Bridging',
  107.                  '80'=>'ATM Logical Port',
  108.                  '81'=>'AT&T DS0 Point (64 Kbps)',
  109.                  '82'=>'AT&T Group of DS0 on a single DS1',
  110.                  '83'=>'BiSync Protocol (BSC)',
  111.                  '84'=>'Asynchronous Protocol',
  112.                  '85'=>'Combat Net Radio',
  113.                  '86'=>'ISO 802.5r DTR',
  114.                  '87'=>'Ext Pos Loc Report Sys',
  115.                  '88'=>'Apple Talk Remote Access Protocol',
  116.                  '89'=>'Proprietary Connectionless Protocol',
  117.                  '90'=>'CCITT-ITU X.29 PAD Protocol',
  118.                  '91'=>'CCITT-ITU X.3 PAD Facility',
  119.                  '92'=>'MultiProtocol Connection over Frame/Relay',
  120.                  '93'=>'CCITT-ITU X213',
  121.                  '94'=>'Asymetric Digitial Subscriber Loop (ADSL)',
  122.                  '95'=>'Rate-Adapt Digital Subscriber Loop (RDSL)',
  123.                  '96'=>'Symetric Digitial Subscriber Loop (SDSL)',
  124.                  '97'=>'Very High Speed Digitial Subscriber Loop (HDSL)',
  125.                  '98'=>'ISO 802.5 CRFP',
  126.                  '99'=>'Myricom Myrinet',
  127.                  '100'=>'Voice recEive and transMit (voiceEM)',
  128.                  '101'=>'Voice Foreign eXchange Office (voiceFXO)',
  129.                  '102'=>'Voice Foreign eXchange Station (voiceFXS)',
  130.                  '103'=>'Voice Encapulation',
  131.                  '104'=>'Voice Over IP Encapulation',
  132.                  '105'=>'ATM DXI',
  133.                  '106'=>'ATM FUNI',
  134.                  '107'=>'ATM IMA',
  135.                  '108'=>'PPP Multilink Bundle',
  136.                  '109'=>'IBM IP over CDLC',
  137.                  '110'=>'IBM Common Link Access to Workstation',
  138.                  '111'=>'IBM Stack to Stack',
  139.                  '112'=>'IBM Virtual IP Address (VIPA)',
  140.                  '113'=>'IBM Multi-Protocol Channel Support',
  141.                  '114'=>'IBM IP over ATM',
  142.                  '115'=>'ISO 802.5j Fiber Token Ring',
  143.                  '116'=>'IBM Twinaxial Data Link Control (TDLC)',
  144.                  '117'=>'Gigabit Ethernet',
  145.                  '118'=>'Higher Data Link Control (HDLC)',
  146.                  '119'=>'Link Access Protocol F (LAPF)',
  147.                  '120'=>'CCITT V.37',
  148.                  '121'=>'CCITT X.25 Multi-Link Protocol',
  149.                  '122'=>'CCITT X.25 Hunt Group',
  150.                  '123'=>'Transp HDLC',
  151.                  '124'=>'Interleave Channel',
  152.                  '125'=>'Fast Channel',
  153.                  '126'=>'IP (for APPN HPR in IP Networks)',
  154.                  '127'=>'CATV MAC Layer',
  155.                  '128'=>'CATV Downstream Interface',
  156.                  '129'=>'CATV Upstream Interface',
  157.                  '130'=>'Avalon Parallel Processor',
  158.                  '131'=>'Encapsulation Interface',
  159.                  '132'=>'Coffee Pot',
  160.                  '133'=>'Circuit Emulation Service',
  161.                  '134'=>'ATM Sub Interface',
  162.                  '135'=>'Layer 2 Virtual LAN using 802.1Q',
  163.                  '136'=>'Layer 3 Virtual LAN using IP',
  164.                  '137'=>'Layer 3 Virtual LAN using IPX',
  165.                  '138'=>'IP Over Power Lines',
  166.                  '139'=>'Multi-Media Mail over IP',
  167.                  '140'=>'Dynamic synchronous Transfer Mode (DTM)',
  168.                  '141'=>'Data Communications Network',
  169.                  '142'=>'IP Forwarding Interface'
  170.                  );
  171.   my($vendor)=0;
  172.   if ($ARGV[0] eq '--vendor') {
  173. $vendor = 1; shift @ARGV};
  174.   my($community,$router) = ($1,$2) if $ARGV[0] =~ /(.*)@(.*)/;
  175.   die <<USAGE  unless $community && $router;
  176. USAGE: cfgmaker [--vendor] 'community'@'router'
  177. use the --vendor option to try and wrestle some better information
  178. from willing livingston and cisco routers ... (may not work)
  179. EXAMPLE:  cfgmaker public@ezwf7.ethz.ch >>mrtg.cfg
  180. USAGE
  181.   print "# Add a WorkDir: /some/path line to this filenn";
  182.     $session = SNMP_Session->open ($router, $community, 161)
  183. || die "Error opening SNMP session to $router";
  184.   
  185.   my($sysDescr,$sysContact,$sysName,$sysLocation,$ifNumber,$sysObjectID) =
  186.     snmpget("$community@$router",
  187.     'sysDescr','sysContact','sysName', 'sysLocation', 'ifNumber', 'sysObjectID');
  188.    $sysDescr =~ s/rn?/<BR>/g;  # Change returns to <BR>
  189.    my($cisco_router_sysid) = '1.3.6.1.4.1.9';
  190.    my($livingston_router_sysid) = '1.3.6.1.4.1.307';
  191.    my($ciscobox) = ($sysObjectID =~ /^$cisco_router_sysid/);
  192.    my($portmaster) = ($sysObjectID =~ /^$livingston_router_sysid/);
  193.     print <<ECHO;
  194. WorkDir: /pkg/mon/www/mrtg/
  195. Refresh: 300
  196. Interval: 5
  197. WriteExpires: yes 
  198. #Global Modifications:
  199. Unscaled[_]: ymwd
  200. Options[_]: bits,growright
  201. YLegend[_]: Bits Per Second
  202. ShortLegend[_]: b/s
  203. LegendI[_]: &nbsp;Bits/s:
  204. LegendO[_]: &nbsp;Bits/s: 
  205. #################################################################
  206. #    Location: $sysLocation
  207. #     Contact: $sysContact
  208. # System Name: $sysName
  209. #
  210. # System Description including Software and Hardware Versions.
  211. #
  212. # $sysDescr
  213. #################################################################
  214. # Modified Mrtg cfgmaker Configuration file for SMNP Equipment
  215. # Last edited - 1999, Mar 31th, revision 2.0
  216. # Edited By   - mpburton (mpburton@europa.com)
  217. # Time        - 11:10 pm
  218. # Created By  - Jlatimer (J.Latimer@sussex.ac.uk)  
  219. ################################################################# 
  220. #---------------------------------------------------------------  
  221. ECHO
  222.   $session->map_table ([[1,3,6,1,2,1,4,20,1,1], # ipAdEntAddr
  223. [1,3,6,1,2,1,4,20,1,2]], # ipAdEntIf
  224.        sub ($@) {
  225.    my ($index, $ipadentaddr, $ipadentif) = @_;
  226.    grep (defined $_ && ($_=pretty_print $_),
  227.  ($ipadentif, $ipadentaddr));
  228.    $ipaddr{$ipadentif} = $ipadentaddr;
  229.    $iphost{$ipadentif} = 
  230.        gethostbyaddr(pack('C4',split(/./,$ipaddr{$ipadentif})), AF_INET);
  231.    if (!defined $iphost{$ipadentif} || ($iphost{$ipadentif} eq '')){
  232.        $iphost{$ipadentif} = 'No hostname defined for IP address';
  233.    }
  234.        });
  235.   print STDERR "Got Addressesn" if $DEBUG;
  236.   print STDERR "Got IfTablen" if $DEBUG;
  237.   my(%sifdesc,%siftype,%sifspeed,%sifadminstatus,%sifoperstatus,%sciscodescr,%sifrawdesc);
  238.   ### May need the cisco IOS version number so we know which oid to use
  239.   ###   to get the cisco description.
  240.   ###
  241.   ### - mjd 2/5/98 (Mike Diehn) (mdiehn@mindspring.net)
  242.   ###
  243.   my ($cisco_ver, $cisco_descr_oid, @ciscodescr);
  244.   if ( $ciscobox ) {
  245.     ($cisco_ver) = ($sysDescr =~ m/Versions+([d.]+)(d/o);
  246.     $cisco_descr_oid = ($cisco_ver ge "11.2") ? "ifAlias" : "CiscolocIfDescr";
  247.   }
  248. #mod by jon: create a hash table to map ifIndex integers to module/port names:
  249. my $cat5500 = 0;
  250. if ( $sysDescr =~ /WS-C55.*/i ) {
  251.   $cat5500 = 1;
  252. }
  253. my (%iftomp, %iftovlan);
  254. if ($cat5500) {
  255. $session->map_table ([[1,3,6,1,4,1,9,5,1,4,1,1,11]], #5500 port group
  256. sub ($@) {
  257.   my ($rowindex, $index) = @_;
  258.   grep (defined $_ && ($_=pretty_print $_),
  259. ($index));
  260. #  $rowindex =~ s/.///g;
  261.   $iftomp{$index} = $rowindex;
  262. #  print "row:$rowindex; idx:$index";
  263. #  print "nn";
  264. });
  265. #foreach my $key (sort(keys %iftomp)) {
  266. #  print $key, '=', $iftomp{$key}, "n";
  267. #}
  268. $session->map_table ([[1,3,6,1,4,1,9,5,1,9,3,1,3]],
  269. sub ($@) {
  270.   my ($rowindex, $vlan_no) = @_;
  271.   grep (defined $_ && ($_=pretty_print $_),
  272.         ($vlan_no));
  273.   my $ifindex;
  274.   foreach my $key (keys %iftomp) {
  275.     if ($iftomp{$key} eq $rowindex) {
  276.       $ifindex = $key;
  277.     }
  278.   }
  279.   $iftovlan{$ifindex} = $vlan_no;
  280. });
  281. #foreach my $key (sort(keys %iftovlan)) {   
  282. #  print $key, '=', $iftovlan{$key}, "n";
  283. #}
  284. } #end if cat5500
  285. $session->map_table ([[1,3,6,1,2,1,2,2,1,1], # ifIndex
  286.       [1,3,6,1,2,1,2,2,1,2], # ifDescr
  287.       [1,3,6,1,2,1,2,2,1,3], # ifType
  288.       [1,3,6,1,2,1,2,2,1,5], # ifSpeed
  289.       [1,3,6,1,2,1,2,2,1,7], # ifAdminStatus
  290.       [1,3,6,1,2,1,2,2,1,8]], # ifOperStatus
  291. sub ($@) {
  292.     my ($rowindex,$index,$ifdescr,$iftype,$ifspeed,$ifadminstatus,$ifoperstatus) = @_;
  293.     grep (defined $_ && ($_=pretty_print $_),
  294.   ($index,$ifdescr,$iftype,$ifspeed,$ifadminstatus,$ifoperstatus));
  295.   if ($cat5500) {
  296.     my ($intname, $tmp_vlan_no) = split (' ',$ifdescr);
  297.     if ( ($intname eq "sc0") || ($intname eq "sl0") ) {
  298.       return;
  299.     }
  300.     if ($intname eq "VLAN") {
  301.       if ($tmp_vlan_no >= 1000) {
  302.         return;
  303.       }
  304. #The Catalyst software version 4.5 seems to return '0' as the ifSpeed for a
  305. #VLAN.  We set it to 100Mb because we want to watch aggregate VLAN traffic.
  306.       if ($ifspeed == 0) {
  307.         $ifspeed = 100 * 10**6;
  308.       }
  309.     }
  310.     my ($port_num, $vlan_desc);
  311.     $port_num = $iftomp{$index};
  312.     $port_num =~ s/.///g;
  313.     if ($iftovlan{$index} != 1) {
  314.       $vlan_desc = "<font color="#8C1717"> Vlan $iftovlan{$index} </font>";
  315.     }
  316.     else {
  317.       $vlan_desc = "Vlan $iftovlan{$index}";
  318.     }
  319.     if ($iftype != 53) {
  320.       $sifdesc{$index} = "Port $port_num, $vlan_desc, $ifdescr";
  321.     }
  322.     else {
  323.       $sifdesc{$index} = "<font color="#6B238E"> <B> Aggregate Traffic: $ifdescr </B> </font>";
  324.       $sifrawdesc{$index} = $ifdescr;
  325.     }
  326.   }
  327.   else {
  328.     $sifdesc{$index} = $ifdescr;
  329.   }
  330.     $siftype{$index} = $iftype;
  331.     $sifspeed{$index} = $ifspeed;
  332.     $sifadminstatus{$index} = $ifadminstatus;
  333.     $sifoperstatus{$index} = $ifoperstatus;
  334.     if ($portmaster && $vendor) {
  335.       
  336.       # We can only approximate speeds
  337.       # 
  338.       # so we think that ppp can do 76800 bit/s, and slip 38400.
  339.       # (actualy, slip is a bit faster, but usualy users with newer modems
  340.       # use ppp). Alternatively, you can set async speed to 115200 or
  341.       # 230400 (the maximum speed supported by portmaster).
  342.       # 
  343.       # But if the interface is ptpW (sync), max speed is 128000
  344.       # change it to your needs. On various Portmasters there are
  345.       # various numbers of sync interfaces, so modify it.
  346.       # 
  347.       #  The most commonly used PM-2ER has only one sync.
  348.       # 
  349.       #  Paul Makeev (mac@redline.ru)
  350.       # 
  351.       if ($siftype{$index} eq '23') {
  352.               if ($sifdesc{$index} eq 'ptpW1') {
  353.                       $sifspeed{$index} = 128000;
  354.               } else {
  355.                       $sifspeed{$index} = 76800;
  356.               }
  357.       } elsif ($siftype{$index} eq '28') {
  358.               $sifspeed{$index} = 38400;
  359.       } elsif ($siftype{$index} eq '6') {
  360.               $sifspeed{$index} = 10000000;
  361.       }
  362.     }
  363.     ### Move this section south so we know what type of
  364.     ###  circuit we're looking at before we retrieve
  365.     ###  the cisco interface alias.
  366.     ###
  367.     ### This whole cicso thing should be re-written, but since
  368.     ###   this script doesn't need to run quickly...
  369.     ###
  370.     ###  - mjd 2/5/98
  371.     ###
  372.     # Get the user configurable interface description entered in the config 
  373.     # if it's a cisco-box
  374.     #
  375.     if ($ciscobox && $vendor) {
  376. my ($enoid, @descr);
  377. $enoid = $cisco_descr_oid . "." . $index;
  378. if ( $cisco_ver ge "11.2" or $siftype{$index} != '32' ) {
  379.   ### This is either not a frame-relay sub-interface or
  380.   ###  this router is running IOS 11.2+ and interface
  381.   ###  type won't matter. In either of these cases, it's
  382.   ###  ok to try getting the ifAlias or ciscoLocIfDesc.
  383.   ###
  384.   @descr = snmpget("$community@$router", $enoid);
  385. } else {
  386.   ### This is a frame-relay sub-interface *and* the router
  387.   ###  is running an IOS older than 11.2. Therefore, we can
  388.   ###  get neither ifAlias nor ciscoLocIfDesc. Do something
  389.   ###  useful.
  390.   ###
  391.   @descr = ("Cisco PVCs descriptions require IOS 11.2+.");
  392. } # end if else
  393. ### Put whatever I got into the array we'll use later to append the result
  394. ###   of this operation onto the results from the ifDescr fetch.
  395. ###
  396. push @ciscodescr, shift @descr;
  397.     } # end if ($cisco_box && $vendor)
  398.     # especially since cisco does not return a if
  399.     # descr for each interface it has ...
  400.     ## JB 2/8/97 - sometimes IOS inserts E1 controllers in the standard-MIB
  401.     ## interface table, but not in the local interface table. This puts the
  402.     ## local interface description table out-of-sync. the following 
  403.     ## modification skips over E1 cards as interfaces.
  404.     #
  405.     ### I suspect that the mod I made above, to use the ifAlias
  406.     ###   oid if possible, may cause problems here. If it seems
  407.     ###   that your descriptions are out of sync, try commenting
  408.     ###   out the "if ( condition )" and it's closing right brace
  409.     ###   so that the "shift @ciscodescr" get executed for *all*
  410.     ###   iterations of this loop.
  411.     ###
  412.     ### - mjd 2/5/95
  413.     ###
  414.     if ($ciscobox && $siftype{$index} != 18) {
  415.           $sciscodescr{$index} = "<BR>" . (shift @ciscodescr) if @ciscodescr;
  416.     }
  417. });
  418.   my $index;
  419.   foreach $index ( sort { $a <=> $b } keys %sifdesc) {
  420.     my $c;
  421.     my $speed = int($sifspeed{$index} / 8); # bits to byte
  422.     my $speed_str=&fmi($speed);
  423.     my $name="$iphost{$index}";
  424.     $name = "$router.$index" if not $name or $name =~ /s/;
  425.   if (($sifadminstatus{$index} != 1)
  426. # this check added by Josh - don't query E1-stack controllers
  427.       || ($siftype{$index} == 18)
  428. || ($siftype{$index} == 24)
  429. || ($speed == 0 ) 
  430. || ($speed > 400 * 10**6)  #speeds of 400 MByte/s are not realistic
  431. || ($sifoperstatus{$index} == 3)) {
  432.     print <<ECHO;
  433. ########
  434. ######## This Interface is one of the following
  435. ######## - administratively not UP
  436. ######## - it is in test mode
  437. ######## - it is a softwareLoopback interface
  438. ######## - has a unrealistic speed setting
  439. ######## It is commented out for this reason.
  440. ########
  441. ECHO
  442.   $c="# ";
  443.   }else {
  444.     $c = '';
  445.   }
  446.     
  447.   print <<ECHO;
  448. ${c}
  449. ECHO
  450. if ( ($cat5500) && ($siftype{$index} == 53) ) {
  451. #  print "nnhere!! desc:$sifrawdesc{$index}nn";
  452.   my $agg_vlan_no = $sifrawdesc{$index};
  453.   $agg_vlan_no =~ s/D//g;
  454.   my $ctr = 0;
  455.   foreach my $key (sort(keys %iftovlan)) {
  456. # print "key:$key;agg:$agg_vlan_no;index:$indexnnnn";
  457.     if ($iftovlan{$key} == $agg_vlan_no) {
  458. #      print "nna hit!!nn";
  459.       if ($ctr == 0) {
  460. print "${c}Target[$name]: $key:$community@$router";
  461.       }
  462.       else {
  463. print " + $key:$community@$router";
  464.       }
  465.       $ctr++;
  466.     }
  467.   }
  468. }
  469. else {
  470.   print "${c}Target[$name]: $index:$community@$router";
  471. }
  472. print <<ECHO;
  473. ${c}
  474. ${c}Directory[$name]:$sysName
  475. ${c}MaxBytes[$name]: $speed
  476. ${c}Title[$name]: $sysName ($iphost{$index}): $sifdesc{$index}
  477. ${c}PageTop[$name]: <H1>Traffic Analysis for $sifdesc{$index}
  478. ${c} $sciscodescr{$index}</H1>
  479. ${c} <TABLE>
  480. ${c}   <TR><TD>System:</TD><TD>$sysName in $sysLocation</TD></TR>
  481. ${c}   <TR><TD>Maintainer:</TD><TD>$sysContact</TD></TR>
  482. ${c}   <TR><TD>Interface:</TD><TD>$sifdesc{$index} ($index)</TD></TR>
  483. ${c}   <TR><TD>IP:</TD><TD>$iphost{$index} ($ipaddr{$index})</TD></TR>
  484. ${c}   <TR><TD>Max Speed:</TD>
  485. ${c}       <TD>$speed_str ($ifType_d{$siftype{$index}})</TD></TR>
  486. ${c}  </TABLE>
  487. ${c}
  488. #---------------------------------------------------------------
  489. ECHO
  490.   }
  491. }
  492.   
  493. main;
  494. exit(0);
  495. sub fmi {
  496.   my($number) = $_[0];
  497.   my(@short);
  498.   @short = ("Bytes/s","kBytes/s","MBytes/s","GBytes/s");
  499.   my $digits=length("".$number);
  500.   my $divm=0;
  501.   while ($digits-$divm*3 > 4) { $divm++; }
  502.   my $divnum = $number/10**($divm*3);
  503.   return sprintf("%1.1f %s",$divnum,$short[$divm]);
  504. }