#! /usr/sepp/bin/perl
# -*- mode: Perl -*-
##################################################################
# MRTG 2.9.4  -- Config file creator
##################################################################
# Created by Tobias Oetiker <oetiker@ee.ethz.ch>
# this produces an mrtg config file for one router or more routers
# by pulling info off the router via snmp
##################################################################
# Distributed under the GNU copyleft
# Copyright 2000 by Tobias Oetiker
##################################################################

# DEBUG TARGETS
# base - basic program flow
@main::DEBUG=qw(base);

require 5.005;
use strict;

BEGIN {
    # Automatic OS detection ... do NOT touch
    if ( $^O =~ /^(?:(ms)?(dos|win(32|nt)?))/i ) {
        $main::OS = 'NT';
        $main::SL = '\\';
        $main::PS = ';';
    } elsif ( $^O =~ /^VMS$/i ) {
        $main::OS = 'VMS';
        $main::SL = '.';
        $main::PS = ':';
    } else {
        $main::OS = 'UNIX';
        $main::SL = '/';
        $main::PS = ':';
    }
}

use FindBin;
use lib "${FindBin::Bin}";
use lib "${FindBin::Bin}${main::SL}..${main::SL}lib${main::SL}mrtg2";

use MRTG_lib "2.090006";
use SNMP_util "0.77";
use SNMP_Session;
use Getopt::Long;
use Pod::Usage;
use Socket;


sub main {
    my %opt;
    my %routers;
    my %confcache;
    init();
    $opt{fullcmd} = "$0 ".(join " ", map {$_ =~ /[ \[\]\*\{\}\;\>\<\&]/ ? "'$_'" : $_ } @ARGV);
    options(\%opt);
    foreach my $router (@ARGV) {
        pod2usage(-verbose=>1,-message=>"ERROR: Could not Parse $router\n")
                unless  $router =~ /.*\@.*/;
	debug('base',"Get Device Info on $router");
	$routers{$router} = DeviceInfo($router);
	debug('base',"Populating confcache");
	populateconfcache(\%confcache,$router,1);
	debug('base',"Get Interface Info");
	InterfaceInfo(\%confcache,\%routers,$router,\%opt)
    }
    GenConf(\%opt,\%routers,\%confcache);
}

main;
exit 0;

sub InterfaceInfo($$$$) {
    my $confcache = shift;
    my $routers = shift;
    my $router = shift;
    my $opt = shift;
    my @Variables = qw (ifIndex ifType ifSpeed
			ifAdminStatus ifOperStatus);
    if ($routers->{$router}{Vendor} eq 'cisco' &&
	$routers->{$router}{sysDescr} =~ m/Version\s+(\d\d\.\d+)/) {
	push @Variables,  ($1 > 11.0) ? "ifAlias" : "CiscolocIfDescr";
    }

    my $descr = $routers->{$router}{sysDescr};                                   
    if ($routers->{$router}{Vendor} eq 'cisco' &&                                
        $descr =~ m/Catalyst\sOperating\sSystem/ ) {                             
        push @Variables,  "CiscoCatalystPortName";                                 
    }                                                                            

    foreach my $var (@Variables) {
	debug('base',"Walking $var");
	foreach my $tuple (snmpwalk($router, $var)){
	    my($if,$value) = split /:/, $tuple, 2;
	    $routers->{$router}{$if}{$var} = $value;
	}
    }
    # magic speed determination for portmaster IFs

    if ($routers->{$router}{Vendor} eq 'portmaster') {
	# We can only approximate speeds
	# 
	# so we think that ppp can do 76800 bit/s, and slip 38400.
	# (actualy, slip is a bit faster, but usualy users with newer modems
	# use ppp). Alternatively, you can set async speed to 115200 or
	# 230400 (the maximum speed supported by portmaster).
	# 
	# But if the interface is ptpW (sync), max speed is 128000
	# change it to your needs. On various Portmasters there are
	# various numbers of sync interfaces, so modify it.
	# 
	#  The most commonly used PM-2ER has only one sync.
	# 
	#  Paul Makeev (mac@redline.ru)
	# 
	foreach my $if (keys %{$routers->{$router}}) {
	    next unless $if =~ /^\d+$/;
	    my $ift = $routers->{$router}{$if}{ifType};
	    my $ifd = $routers->{$router}{$if}{RDescr};
	    if ($ift ==  23) {
		if ($ifd eq 'ptpW1') {
		    $routers->{$router}{$if}{ifSpeed} = 128000;
		} else {
		  $routers->{$router}{$if}{ifSpeed} = 76800;
	      }
	    } elsif ($ift == 28) {
		$routers->{$router}{$if}{ifSpeed} = 38400;
	    } elsif ($ift == 6) {
		$routers->{$router}{$if}{ifSpeed} = 10000000;
	    }
	}
    }

    # match confcache info into tree
        foreach my $method (keys %{$$confcache{$router}}) {
            foreach my $key (keys %{$$confcache{$router}{$method}}) {
		my $if = $$confcache{$router}{$method}{$key};
                next unless $if =~ /^\d+$/;
		$routers->{$router}{$if}{$method} = $key;
		for ($method) {
		    #fix special chars in ifdescr
		    /^Descr|Name$/ && do {
                        $routers->{$router}{$if}{"R$method"} = $routers->{$router}{$if}{$method};
			$routers->{$router}{$if}{$method} =~ s/([ :])/\\$1/g;
			next;
		    };
		    #find hostname of IF
                    
		    not $$opt{noreversedns} && /^Ip$/ && do {
			my $name =
			  gethostbyaddr(
					pack('C4',
					     split(/\./,
						   $routers->{$router}{$if}{$method})),
					AF_INET);
         		$routers->{$router}{$if}{DNSName} = ($name or "");
			next;
		    };
		}
            }
        
    }
}

sub GenConf ($$$) {
    my $opt = shift;
    my $routers = shift;
    my $confcache = shift;
    my $conf = "# Created by \n# $$opt{fullcmd}\n\n";
    
    # print global options
    if (defined $$opt{global}) {
	foreach my $key (@{$$opt{global}}) {
	    $conf .= "$key\n";
	}
    } else {
	$conf .= <<ECHO;

### Global Config Options

#  for UNIX
# WorkDir: /home/http/mrtg

#  or for NT
# WorkDir: c:\\mrtgdata

### Global Defaults

#  to get bits instead of bytes and graphs growing to the right
# Options[_]: growright, bits

ECHO
    }
    foreach my $router (sort keys %$routers ) {
	my $s = $routers->{$router};
	$conf .= <<ECHO;

######################################################################
# System: $$s{sysName}
# Description: $$s{sysDescr}
# Contact: $$s{sysContact}
# Location: $$s{sysLocation}
######################################################################


ECHO

	foreach my $key (sort {int($a) <=> int($b)} keys %{$routers->{$router}}) {
	    next unless $key =~ /^\d+$/;
	    my $i = $routers->{$router}{$key};
            
       	    $conf .= "### Interface $key >> Descr: '$$i{RDescr}' | Name: '$$i{RName}' | Ip: '$$i{Ip}' | Eth: '$$i{Eth}' ###\n";
	    # does it make sense to look at the interface ?
	    my @prob;
	    my $c = "";
            if (not defined $$opt{'no-down'}) {
	     push @prob, "it is Administratively DOWN" 
	      if $$i{ifAdminStatus} == 2;

	     push @prob, "it is Operationally DOWN" 
	      if $$i{ifOperStatus} == 2;

	     push @prob, "it is in administrative TEST mode" 
	      if $$i{ifAdminStatus} == 3;

	     push @prob, "it is in operational TEST mode" 
	      if $$i{ifOperStatus} == 3;
            }
	    push @prob, "it is a DS1 controllers"
	      if $$i{ifType} == 18; # by fwo@obsidian.co.za

	    push @prob, "it is a E1 controllers"
	      if $$i{ifType} == 19; # by fwo@obsidian.co.za

	    push @prob, "it is a Software Loopback interface" 
	      if $$i{ifType} == 24;

            push @prob, "it is a DS3 contorller"
              if $$i{ifType} == 30; # by blube@floridadigital.net

#            push @prob, "agregate cisco interface interface does not count traffic"
#              if $$s{Vendor} eq 'cisco' and
#                 $$i{ifType} == 53;

            push @prob, "it is a CEF Sub-interface" # John Begley <maslow@mediaone.net>
              if $$i{ifType} == 162;

	    push @prob, "has a speed of $$i{ifSpeed} which makes no sense" 
	      if $$i{ifSpeed} == 0;

	    push @prob, "it is a cisco Null0 interface"
	      if $$s{Vendor} eq 'cisco' and
		 $$i{Descr} eq 'Null0';

	    push @prob, "it is a cisco VLAN interface"
	      if $$s{Vendor} eq 'cisco' and
		 $$i{Descr} =~ /^VLAN\d+$/;

            my $message;
            push @prob, "got '$message' from interface when trying to query"
               if ($message = IsCounterBroken($key, $router));
                    

	    # determine interface reference
	    my $ifref;
	    if (defined $$opt{ifref}) {
		for ($$opt{ifref}) {
		    /^ip$/ && do { $ifref = "/".$$i{Ip} if $$i{Ip}  ; last};
		    /^eth$/ && do { $ifref = "!".$$i{Eth} if $$i{Eth}; last};
		    /^descr$/ && do {$ifref = "\\".$$i{Descr} if $$i{Descr}; last};
		    /^name$/ && do {$ifref = "#".$$i{Name} if $$i{Name}; last};
		    /^type$/ && do {$ifref = "%".$$i{Type} if $$i{Type}; last};
		    /^nr$/ && do {$ifref = $key; last};
		    die "ERROR: Invalid value for --ifref: '$$opt{ifref}'\n";
		}
		if (not defined $ifref) {
		    push @prob, "--ifref=$$opt{ifref} is not unique for this interface";
		    $ifref = $key;
		}
	    } else {
		$ifref = $key;
	    }

	    # issue problem report

	    if (@prob) {
		$c = "# ";
		$conf .= "### The following interface is commented out because:\n";
		map {$conf .= "### * $_\n"} @prob;
	    }

	    # generate Target name
	    my $reftrim = $ifref;
	    $reftrim =~ s/[#!\/\\:\s\@%]+/_/g;
	    $reftrim =~ s/^_*(.+?)_*$/$1/;
	    $router =~ /\@([^:]+)/;
            my $router_name = $1;
	    my $name = "$1_$reftrim";
            my $refsimp = $ifref;
            $refsimp =~ s/^[^\d]//;
	    my $speed = int($$i{ifSpeed} / 8);
	    my $speed_str = fmi($speed,$opt);
	    my $iftype = IfType($$i{ifType});
            my $refdesc = 'Traffic Analysis for ';
            if (defined $$opt{descint}) {
                $refdesc = '';
                $refsimp = $iftype;
                $refsimp =~ s/^$/$$i{RDescr}/;
            }

            my $port_dot = $$i{RName};                                             
            $port_dot =~ s/\//./g;                                                 
            my $portname = $routers->{$router}{$port_dot}{CiscoCatalystPortName};  

             $conf .= <<ECHO;
${c}
${c}Target[$name]: $ifref:$router
${c}SetEnv[$name]: MRTG_INT_IP="$$i{Ip}" MRTG_INT_DESCR="$$i{RDescr}"
ECHO
             if (defined $$opt{subdirs}) {
		 my $directory_name = $$opt{subdirs};
		 $directory_name =~ s/HOSTNAME/$router_name/g;
		 $directory_name =~ s/SNMPNAME/$$s{sysName}/g;

                 $conf .= "${c}Directory[$name]: $directory_name\n";
             }
             $conf .= <<ECHO;
${c}MaxBytes[$name]: $speed
${c}Title[$name]: $refdesc$refsimp -- $$s{sysName}
${c}PageTop[$name]: <H1>$refdesc$refsimp -- $$s{sysName}</H1>
${c} <TABLE>
${c}   <TR><TD>System:</TD>     <TD>$$s{sysName} in $$s{sysLocation}</TD></TR>
${c}   <TR><TD>Maintainer:</TD> <TD>$$s{sysContact}</TD></TR>
${c}   <TR><TD>Description:</TD><TD>$$i{RDescr} $$i{ifAlias} $$i{CiscolocIfDescr}</TD></TR>
${c}   <TR><TD>ifType:</TD>     <TD>$iftype ($$i{ifType})</TD></TR>
${c}   <TR><TD>ifName:</TD>     <TD>$$i{RName}</TD></TR>
ECHO
             $conf .= <<ECHO if defined $portname;
${c}   <TR><TD>Port Name:</TD>  <TD>$portname</TD></TR>
ECHO
             $conf .= <<ECHO;
${c}   <TR><TD>Max Speed:</TD>  <TD>$speed_str</TD></TR>
ECHO

        $conf .= <<ECHO if defined $$i{Ip};
${c}   <TR><TD>Ip:</TD>         <TD>$$i{Ip} ($$i{DNSName})</TD></TR>
ECHO
        $conf .= <<ECHO;
${c} </TABLE>


ECHO

	}
    }
    if ($$opt{output}) {
	debug ('base', "Writing $$opt{output}");
	open X, ">$$opt{output}" or die "ERROR: creating $$opt{output}: $!\n";
	print X $conf;
	close X;
    } else {
	print $conf;
    }
}

sub IsCounterBroken ($$) {
    my $if = shift;
    my $router = shift;
    $SNMP_Session::suppress_warnings = 3;
    snmpget($router, 'ifInOctets.'.$if);
    if (defined $SNMP_Session::errmsg) {
        my $error = $SNMP_Session::errmsg;
        $SNMP_Session::errmsg = undef;
        $error =~ s/\n/\n###     /g;
        return $error;
    }
    return 0;
}

sub DeviceInfo ($) {
    my $router=shift;
    my @variables = qw(sysDescr sysContact
		       sysName sysLocation
		       sysObjectID);
    my %DevInfo;
    if (@DevInfo{@variables} = snmpget($router, @variables)) {
	# remove \r from sysDescr
	$DevInfo{sysDescr} =~ s/[\n\r]+/\n#          /g;
        # vendor identification
	for ($DevInfo{sysObjectID}) {
	    $DevInfo{Vendor} = 'cisco' if /^\Q1.3.6.1.4.1.9.\E/;
	    $DevInfo{Vendor} = 'portmaster' if /^\Q1.3.6.1.4.1.307.\E/;
            debug('base',"Vendor Id: $DevInfo{Vendor}");
	};
	return \%DevInfo;
    } else {
	# we just die because the snmp module has already complained
	exit 1;
    }
}


sub fmi ($$) {
    my $number = shift;
    my $opt = shift;
    my(@short);
    if (grep /^options\[[_^\$]\].+bits/i, @{$$opt{"global"}}){
	$number*=8;
	@short = ("bits/s","kbits/s","Mbits/s","Gbits/s");
    } else {
	@short = ("Bytes/s","kBytes/s","MBytes/s","GBytes/s");
    }
    my $digits=length("".$number);
    my $divm=0;
    while ($digits-$divm*3 > 4) { $divm++; }
    my $divnum = $number/10**($divm*3);
    return sprintf("%1.1f %s",$divnum,$short[$divm]);
}


sub IfType ($) {
  return {'1'=>'Other',
	  '2'=>'regular1822',
	  '3'=>'hdh1822',
	  '4'=>'ddnX25',
	  '5'=>'rfc877x25',
	  '6'=>'ethernetCsmacd',
	  '7'=>'iso88023Csmacd',
	  '8'=>'iso88024TokenBus',
	  '9'=>'iso88025TokenRing',
	  '10'=>'iso88026Man',
	  '11'=>'starLan',
	  '12'=>'proteon10Mbit',
	  '13'=>'proteon80Mbit',
	  '14'=>'hyperchannel',
	  '15'=>'fddi',
	  '16'=>'lapb',
	  '17'=>'sdlc',
	  '18'=>'ds1',
	  '19'=>'e1',
		 '20'=>'basicISDN',
	  '21'=>'primaryISDN',
	  '22'=>'propPointToPointSerial',
	  '23'=>'ppp',
	  '24'=>'softwareLoopback',
	  '25'=>'eon',
	  '26'=>'ethernet-3Mbit',
	  '27'=>'nsip',
	  '28'=>'slip',
	  '29'=>'ultra',
	  '30'=>'ds3',
	  '31'=>'sip',
	  '32'=>'frame-relay',
	  '33'=>'rs232',
	  '34'=>'para',
	  '35'=>'arcnet',
	  '36'=>'arcnetPlus',
	  '37'=>'atm',
	  '38'=>'miox25',
	  '39'=>'sonet',
	  '40'=>'x25ple',
	  '41'=>'iso88022llc',
	  '42'=>'localTalk',
	  '43'=>'smdsDxi',
	  '44'=>'frameRelayService',
	  '45'=>'v35',
	  '46'=>'hssi',
	  '47'=>'hippi',
	  '48'=>'modem',
	  '49'=>'aal5',
	  '50'=>'sonetPath',
	  '51'=>'sonetVT',
	  '52'=>'smdsIcip',
	  '53'=>'propVirtual',
	  '54'=>'propMultiplexor',
	  '55'=>'100BaseVG',
	  '56'=>'Fibre Channel',
	  '57'=>'HIPPI Interface',
	  '58'=>'Obsolete for FrameRelay',
	  '59'=>'ATM Emulation of 802.3 LAN',
	  '60'=>'ATM Emulation of 802.5 LAN',
	  '61'=>'ATM Emulation of a Circuit',
	  '62'=>'FastEthernet (100BaseT)',
	  '63'=>'ISDN & X.25',
	  '64'=>'CCITT V.11/X.21',
	  '65'=>'CCITT V.36',
	  '66'=>'CCITT G703 at 64Kbps',
	  '67'=>'Obsolete G702 see DS1-MIB',
	  '68'=>'SNA QLLC',
	  '69'=>'Full Duplex Fast Ethernet (100BaseFX)',
	  '70'=>'Channel',
	  '71'=>'Radio Spread Spectrum (802.11)',
	  '72'=>'IBM System 360/370 OEMI Channel',
	  '73'=>'IBM Enterprise Systems Connection',
	  '74'=>'Data Link Switching',
	  '75'=>'ISDN S/T Interface',
	  '76'=>'ISDN U Interface',
	  '77'=>'Link Access Protocol D (LAPD)',
	  '78'=>'IP Switching Opjects',
	  '79'=>'Remote Source Route Bridging',
	  '80'=>'ATM Logical Port',
	  '81'=>'AT&T DS0 Point (64 Kbps)',
	  '82'=>'AT&T Group of DS0 on a single DS1',
	  '83'=>'BiSync Protocol (BSC)',
	  '84'=>'Asynchronous Protocol',
	  '85'=>'Combat Net Radio',
	  '86'=>'ISO 802.5r DTR',
	  '87'=>'Ext Pos Loc Report Sys',
	  '88'=>'Apple Talk Remote Access Protocol',
	  '89'=>'Proprietary Connectionless Protocol',
	  '90'=>'CCITT-ITU X.29 PAD Protocol',
	  '91'=>'CCITT-ITU X.3 PAD Facility',
	  '92'=>'MultiProtocol Connection over Frame/Relay',
	  '93'=>'CCITT-ITU X213',
	  '94'=>'Asymetric Digitial Subscriber Loop (ADSL)',
	  '95'=>'Rate-Adapt Digital Subscriber Loop (RDSL)',
	  '96'=>'Symetric Digitial Subscriber Loop (SDSL)',
	  '97'=>'Very High Speed Digitial Subscriber Loop (HDSL)',
	  '98'=>'ISO 802.5 CRFP',
	  '99'=>'Myricom Myrinet',
	  '100'=>'Voice recEive and transMit (voiceEM)',
	  '101'=>'Voice Foreign eXchange Office (voiceFXO)',
	  '102'=>'Voice Foreign eXchange Station (voiceFXS)',
	  '103'=>'Voice Encapulation',
	  '104'=>'Voice Over IP Encapulation',
	  '105'=>'ATM DXI',
	  '106'=>'ATM FUNI',
	  '107'=>'ATM IMA',
	  '108'=>'PPP Multilink Bundle',
	  '109'=>'IBM IP over CDLC',
	  '110'=>'IBM Common Link Access to Workstation',
	  '111'=>'IBM Stack to Stack',
	  '112'=>'IBM Virtual IP Address (VIPA)',
	  '113'=>'IBM Multi-Protocol Channel Support',
	  '114'=>'IBM IP over ATM',
	  '115'=>'ISO 802.5j Fiber Token Ring',
	  '116'=>'IBM Twinaxial Data Link Control (TDLC)',
	  '117'=>'Gigabit Ethernet',
	  '118'=>'Higher Data Link Control (HDLC)',
	  '119'=>'Link Access Protocol F (LAPF)',
	  '120'=>'CCITT V.37',
	  '121'=>'CCITT X.25 Multi-Link Protocol',
	  '122'=>'CCITT X.25 Hunt Group',
	  '123'=>'Transp HDLC',
	  '124'=>'Interleave Channel',
	  '125'=>'Fast Channel',
	  '126'=>'IP (for APPN HPR in IP Networks)',
	  '127'=>'CATV MAC Layer',
	  '128'=>'CATV Downstream Interface',
	  '129'=>'CATV Upstream Interface',
	  '130'=>'Avalon Parallel Processor',
	  '131'=>'Encapsulation Interface',
	  '132'=>'Coffee Pot',
	  '133'=>'Circuit Emulation Service',
	  '134'=>'ATM Sub Interface',
	  '135'=>'Layer 2 Virtual LAN using 802.1Q',
	  '136'=>'Layer 3 Virtual LAN using IP',
	  '137'=>'Layer 3 Virtual LAN using IPX',
	  '138'=>'IP Over Power Lines',
	  '139'=>'Multi-Media Mail over IP',
	  '140'=>'Dynamic synchronous Transfer Mode (DTM)',
	  '141'=>'Data Communications Network',
	  '142'=>'IP Forwarding Interface',
          '162'=>'Cisco Express Forwarding Interface',

	  }->{(shift)};
}

sub options () {
   my $opt = shift;
   GetOptions( $opt,
   	'help|?',
	'man',
        'subdirs=s',
        'no-down',
        'descint',
        'noreversedns',
	'ifref=s',
	'output=s',
	'global=s@' ) or pod2usage(2);

   pod2usage(-exitstatus => 0, -verbose => 2) if $$opt{man};
   pod2usage(-verbose => 1) if $$opt{help} or not @ARGV;


}


sub init () {
  snmpmapOID('sysObjectID' => '1.3.6.1.2.1.1.2.0',
             'CiscolocIfDescr' => '1.3.6.1.4.1.9.2.2.1.1.28',
             'CiscoCatalystPortName' => '1.3.6.1.4.1.9.5.1.4.1.1.4',  
	     'ifAlias' => '1.3.6.1.2.1.31.1.1.1.18');
}

__END__

=head1 NAME

cfgmaker - Creates mrtg.cfg files (for mrtg-2.9.4)

=head1 SYNOPSIS

cfgmaker [options] community@router [community@router ...]

=head1 OPTIONS 

 --ifref=nr	   interface references by Interface Number (default)
 --ifref=ip	                    ... by Ip Address
 --ifref=eth                        ... by Ethernet Number
 --ifref=descr                      ... by Interface Description
 --ifref=name                       ... by Interface Name
 --ifref=type                       ... by Interface Type

 --global "x: a"   add global config entries

 --no-down         do not look at admin or opr status of interfaces

 --descint         describe interface instead of just 'Traffic Analysis for'

 --subdirs=format  give each router its own subdirectory, naming each per 
                   "format", in which HOSTNAME and SNMPNAME will be 
                   replaced by the values of those items -- for instance,  
                   --subdirs=HOSTNAME or --subdirs="HOSTNAME (SNMPNAME)"

 --noreversedns    do not reverse lookup ip numbers

 --help            brief help message
 --man             full documentation

 --output=file     output filename default is STDOUT

=head1 DESCRIPTION

B<Cfgmaker> creates MRTG configuration files based on information
pulled from a router or another SNMP manageable device.

=over

=item I<community>B<@>I<router>

I<Community> is the community name of the device you want to create a
configuration for. The default community name is 'B<public>'; you might
want to try this first if you do not know the community name of a
device. If you are using the wrong comunity name you will get no
response from the device.

I<Router> is the DNS name or the IP number of an SNMP-managable device.           
Following the name you can specify 6 further options separated by                 
colons.  The full syntax looks like this:                                         
 
   B<router>[:[B<port>][:[B<timeout>][:[B<retries>][:[B<backoff>][:B<version>]]]]]

Of special interest may be the last parameter, B<version>.  If you set            
this to '2' then your device will be queried with SNMP version 2                  
requests. This allows to poll the 64 bit traffic counters in the device           
and will thus work much better with fast interfaces (no more counter              
overrun).                                                                         
 

=item B<--help>

Print a brief help message and exit.

=item B<--man>

Prints the manual page and exits.

=item B<--ifref> B<nr>|B<ip>|B<eth>|B<descr>|B<name>

Select the interface identification method.  Default is B<nr> which
identifies the router interfaces by their number.  Unfortunately the
interface numbering scheme in an SNMP tree can change. Some routers
change their numbering when new interfaces are added, others change
thier numbering every full moon just for fun.

To work around this sad problem MRTG can identify interfaces by 3
other properties. None of these works for all interfaces, but you
should be able to find one which does fine for you. Note that
especially ethernet addrsses can be problematic as some routers have
the same ethernet address on most of their interface cards.

Select B<ip> to identify the interface by its IP number. Use B<eth> to
use the ethernet address for identification. Or use B<descr> to use
the Interface description.

If your chosen method does not allow unique interface identification on           
the device you are querying, B<cfgmaker> will tell you about it.                  
 
=item B<--global> B<">I<bla: abc>B<">

Use this to add global options to the generated config file. 
You can call B<--global> several times to add multiple options.

 --global "workdir: /home/mrtg"

If you want some default Options you might want to put

 --global "options[_]: growright,bits"

=item B<--noreversedns>

Do not try to reverse lookup IP numbers ... a must for DNS free environments.

=item B<--no-down>

Normally cfgmaker will not include interfaces which are marked
anything but administratively and operationally UP. With this
switch you get them all.

=item B<--subdirs> I<format>

Give each router its own subdirectory for the HTML and graphics (or
.rrd) files.  The directory name is the given I<format> string with a
couple of pattern replacements.  The string "HOSTNAME" will be
replaced by the hostname of the router (however you specified it on
the B<cfgmaker> commandline -- it may be an actual hostname or just an
IP address), and "SNMPNAME" will be replaced with the device's idea of
its own name (the same name that appears on the right side of the
"Title" lines).  For instance, a call like:

 cfgmaker --subdirs=HOSTNAME__SNMPNAME public@10.10.0.18

would result in the generation of lines looking something like:

 Directory[10.10.0.18_1]: 10.10.0.18__fp2200-bothrip-1.3

=back

=head1 EXAMPLE

This example creates a config file for I<router.place.xyz>:  the router           
has the community name I<public>.  Interfaces get identified by their             
IP number.  Two global options get added to the config file.  The                 
config file gets redirected to I<mrtg.conf>.  The '\' signs at the end            
of the line mean that this command should be written on a single line.            

 cfgmaker --global "WorkDir: /home/tobi"           \
          --global "Options[_]: growright,bits"    \
          --ifref=ip                               \
          public@router.place.xyz > mrtg.cfg

=head1 SEE ALSO

L<reference>

=head1 AUTHOR

Tobias Oetiker E<lt>tobi@oetiker.chE<gt>

=head1 LICENSE

GNU General Public License

=head1 COPYRIGHT

Cfgmaker is Copyright 2000 by Tobias Oetiker E<lt>tobi@oetiker.chE<gt>

=cut
