Re: [Q] Query a router for it's routing table

Doug Hughes (Doug.Hughes@Eng.Auburn.EDU)
Tue, 17 Jun 1997 08:19:30 -0500

>I imagine that this is a simple request, or at least I hope so. I was hoping
>somebody might have some sample source code to query a router for it's
>routing table. I'm writing a discovery algorithm to find all the routers
>that are connected to the seed router. To do this, I need to be able to
>query a router for two peices of information:
>1) It's routing table: I know this is done by using an snmp request for the
>routing table, and then successive requests to get the next entry, and the
>next one, and so on. I just don't know enough to be able to do it.
>2) It's interfaces: I need to find out all the interfaces that the router
>has, so I can determine the difference between a hop to a router, and one to
>a network.
>
>I'm a good tcl programmer, I just don't have any experience with Scotty.
>Thus, I'd like to take a look at some sample code in order to see how this
>is done. If you have some sample code that does one, or both, of the above
>things, I'd appreciate a look. As a note, this is for a commercial product.
>Thus, if you don't want me to use your code, let me know. I don't intend to
>copy any code verbatim, but it's best to state such things beforehand.
>
> Thanks in advance,
> Robert Seeger
>
>PS: Any pointers to information pertaining to these questions would be
>appreciated also. Can't hurt to look at a page that discusses algorithms for
>such things, too.

If you just really want the index of interfaces,
$s walk x ifIndex {puts $x} will give it to you
Instead of just getting the list of interfaces, it might be useful to
get the list of up interfaces.

$s walk x ifAdminStatus {command}
or
$s walk x ifOperStatus {command}

The difference between AdminStatus and OperStatus is that AdminStatus
is a person turing the port off, and OperStatus is the equivalent of
no carrier, or link-down.

routing table is in ipRouteTable

Dumping it will give you probably more information than you want,
so maybe you just want ipRouteDest which returns an IP address.
ipRouteMetric1 might be useful too if you use different route types
like RIP, OSPF, EGP, IGRP, etc..

I'm including a simple program that I wrote that does an SNMP equivalent
of a traceroute. It draws little circles representing the hops, and tries
to get SNMP information from each node. Many nodes out there won't
respond to SNMP (for administrative reasons), so it will do an ICMP
nexthop calculation in that case.

Anyway, it does pretty much what you want.
calculate next hop
calculate pipe bandwidth
calculate interface description

#!/opt/tcl7.5/bin/wish

load /opt/tcl7.5/lib/tnm2.1.4.so tnm

proc dodialog {widget title msg} {

if {[winfo exists $widget]} {return}
toplevel $widget -class Dialog
wm title $widget "$title"

message $widget.m -text "$msg" -width 300 -font helvetica-bold-14

button $widget.b -text OK -command "destroy $widget"

pack $widget.m -side top -expand true -fill both
pack $widget.b -side top -expand false -fill y
}

lappend auto_path /home/ens/doug/tcl $tk_library/demos

if {[llength $argv] < 1} {
puts "Usage: snmptrace dest_host"
exit
}
set d_host [lindex $argv 0]

#puts "Starting at $s_host to $d_host"

if {![string match {[0-9.]*} $d_host]} {
set d_final [nslook $d_host]
} else {
set d_final $d_host
}

#canvas .c -relief flat -width 800 -height 225
#pack .c
set x 50
set y 75

set s [snmp session]
set s2 [snmp session]
set hop 1
set node1 ""
set t [lindex [icmp trace $hop $d_host] 0]
puts "$t $d_final"
while {[string compare [lindex $t 0] $d_final] != 0} {
if {$x > 500} {
set x 50
set y [expr $y + 75]
}
set newnode [mkNode $x $y node$hop]
update idletasks
set node2 $node1
set node1 [.c find withtag node$hop]
set new [.c create text $x $y -tags node$hop -text "$hop"]
set nodeX($new) $x
set nodeY($new) $y
set edgeFirst($new) {}
set edgeSecond($new) {}
if {$node2 != ""} {
set edge [mkEdge $node1 $node2]
update idletasks
}
set x [expr $x + 50]
set y [expr $y + 5]
$s configure -address [lindex $t 0]
# track down next route with ICMP timeout
catch {set oldaddr $haddr} e
set t [lindex [icmp trace $hop $d_host] 0]
set haddr [lindex $t 0]
set i_p [split $haddr {.}]
set dnet ""
# Find destination net
append dnet [lindex $i_p 0] "." [lindex $i_p 1] "." [lindex $i_p 2] ".0"
puts "haddr $haddr $dnet"

# Get output interface for previous router
if {![regexp read $e]} {
$s2 configure -address $oldaddr
if {![catch {set outport [$s2 get ipRouteIfIndex.$dnet]}]} {
set pout [lindex [lindex $outport 0] 2]
append msg($oldaddr) " leaving port $pout"
puts "pout $pout"
}
}

# Try to resolve name
if [catch {set hname [nslook $haddr]} err] {
set hname $haddr
}
# Get SNMP information
if [catch {set port [lindex [$s get ip.ipRouteTable.ipRouteEntry.ipRouteIfIndex.$dnet] 0]} err] {
set msg($haddr) "hop $hop to $hname - no SNMP info"
} else {
set port [lindex $port 2]
set descr [lindex [$s get interfaces.ifTable.ifEntry.ifDescr.$port] 0]
set descr [lindex $descr 2]
set speed [lindex [$s get interfaces.ifTable.ifEntry.ifSpeed.$port] 0]
set speed [expr [lindex $speed 2] / 1000 ]
set msg($haddr) "hop $hop to $hname port$port ($descr) at $speed Kbits/s"
if {$node2 != ""} {
case $speed in {
100000 ".c itemconfigure $edge -fill red -width 5"
10000 ".c itemconfigure $edge -width 5"
1544 ".c itemconfigure $edge -fill red"
768 ".c itemconfigure $edge -fill blue"
56 ".c itemconfigure $edge -fill green"
* ".c itemconfigure $edge -fill gray"
}
}
}
puts $msg($haddr)
.c bind node$hop <Button-3> "dodialog .m$hop \"Node $hop info\" {$msg($haddr)} "
set hop [expr $hop + 1]
}
puts done

bind .c <Key-q> exit
bind . <Key-q> exit

--
____________________________________________________________________________
Doug Hughes					Engineering Network Services
System/Net Admin  				Auburn University
			doug@eng.auburn.edu

--
!! This message is brought to you via the `tkined & scotty' mailing list.
!! Please do not reply to this message to unsubscribe. To subscribe or
!! unsubscribe, send a mail message to <tkined-request@ibr.cs.tu-bs.de>.
!! See http://wwwsnmp.cs.utwente.nl/~schoenw/scotty/ for more information.