diff options
Diffstat (limited to 'example/gethostbyaddr')
-rwxr-xr-x | example/gethostbyaddr | 333 |
1 files changed, 333 insertions, 0 deletions
diff --git a/example/gethostbyaddr b/example/gethostbyaddr new file mode 100755 index 0000000..513a330 --- /dev/null +++ b/example/gethostbyaddr @@ -0,0 +1,333 @@ +#!/bin/sh +# -*- tcl -*- +# The next line is executed by /bin/sh, but not tcl \ +exec tclsh "$0" ${1+"$@"} + +package require Expect + + +# +# gethostbyaddr a.b.c.d - translate an internet address to a FQDN, +# guessing (a lot) if necessary. +# Author: Don Libes, NIST +# Version 4.0 +# Written: January 11, 1991 +# Last revised: March 21, 1996 + +# By default, return a FQDN (fully qualified domain name) or descriptive +# string (if FQDN is not easily determinable). This is tagged with a brief +# explanation of how it was determined. +# +# If the host part of the FQDN cannot be determined, the original IP address +# is used. +# +# Optional arguments act as toggles: Default +# -t tag names with a description of how derived. true +# -v verbose. false +# -r reverse names to see if they resolve back to orig IP address. true +# -n query nic for a descriptive string if it begins to look like true +# the FQDN may be hard to derive. +# -d turn on debugging to expose underlying dialogue false +# +# These options and others (see below) may be set in a ~/.gethostbyaddr file +# To set options from that file, use the same syntax as below. +set timeout 120 ;# timeout query after this many seconds +set tag 1 ;# same as -t +set reverse 1 ;# same as -r +set verbose 0 ;# same as -v +set nic 1 ;# same as -n +set debug 0 ;# same as -d +log_user 0 + +proc usage {} { + send_user "usage: gethostbyaddr \[options\] a.b.c.d\n" + send_user "options meaning (all options act as toggles) default\n" + send_user " -t tag with derivation description true\n" + send_user " -v verbose false\n" + send_user " -r reverse back to IP addr for verification true\n" + send_user " -n query nic true\n" + send_user " -d produce debugging output false\n" + send_user "options must be separate.\n" + exit +} + +if {[file readable ~/.gethostbyaddr]} {source ~/.gethostbyaddr} + +while {[llength $argv]>0} { + set flag [lindex $argv 0] + switch -- $flag \ + "-v" { + set verbose [expr !$verbose] + set argv [lrange $argv 1 end] + } "-r" { + set reverse [expr !$reverse] + set argv [lrange $argv 1 end] + } "-n" { + set nic [expr !$nic] + set argv [lrange $argv 1 end] + } "-t" { + set tag [expr !$tag] + set argv [lrange $argv 1 end] + } "-d" { + set debug [expr !$debug] + set argv [lrange $argv 1 end] + debug $debug + } default { + break + } +} + +set IPaddress $argv + +if {[llength $argv]!=1} usage +if {4!=[scan $IPaddress "%d.%d.%d.%d" a b c d]} usage + +proc vprint {s} { + global verbose + + if {!$verbose} return + send_user $s\n +} + +# dn==1 if domain name, 0 if text (from nic) +proc printhost {name how dn} { + global reverse tag IPaddress + + if {$dn && $reverse} { + set verified [verify $name $IPaddress] + } else {set verified 0} + + if {$verified || !$reverse || !$dn} { + if {$tag} { + send_user "$name ($how)\n" + } else { + send_user "$name\n" + } + + if {$verified || !$reverse} { + close + wait + exit + } + } +} + +# return 1 if name resolves to IP address +proc verify {name IPaddress} { + vprint "verifying $name is $IPaddress" + set rc 0 + spawn nslookup + expect ">*" + send $name\r + + expect { + -re "\\*\\*\\* (\[^\r]*)\r" { + vprint $expect_out(1,string) + } timeout { + vprint "timed out" + } -re "Address:.*Address: (\[^\r]*)\r" { + set addr2 $expect_out(1,string) + if {[string match $IPaddress $addr2]} { + vprint "verified" + set rc 1 + } else { + vprint "not verified - $name is $addr2" + } + } + } + close + wait + return $rc +} + +set bad_telnet_responses "(telnet:|: unknown).*" + +proc telnet_error {s} { + regexp ": (.*)\r" $s dontcare msg + vprint $msg +} + +proc guessHost {guess} { + global guessHost + if {[info exists guessHost]} return + set guessHost $guess +} + +proc guessDomain {guess} { + global guessDomain + if {[info exists guessDomain]} return + set guessDomain $guess +} + +proc guessFQDN {} { + global guessHost guessDomain + return $guessHost.$guessDomain +} + +###################################################################### +# first do a simple reverse nslookup +###################################################################### + +vprint "using nslookup" +spawn nslookup +expect ">*" +send "set query=ptr\r" +expect ">*" +send "$d.$c.$b.$a.in-addr.arpa\r" +expect { + timeout { + vprint "timed out" + } -re "\\*\\*\\* (\[^\r]*)\r" { + vprint $expect_out(1,string) + } -re "name = (\[^\r]*)\r" { + set host $expect_out(1,string) + printhost $host nslookup 1 + + # split out hostname from FQDN as guess for later + guessHost [lindex [split $host "."] 0] + } +} + +close +wait + +###################################################################### +# next telnet to host and ask it what its name is +###################################################################### + +vprint "talking smtp to $IPaddress" +spawn telnet $IPaddress smtp +expect { + -re $bad_telnet_responses { + telnet_error $expect_out(buffer) + } timeout { + vprint "timed out" + } -re "\n220 (\[^\\. ]*).?(\[^ ]*)" { + set host $expect_out(1,string) + set domain $expect_out(2,string) + printhost $host.$domain smtp 1 + + # if not valid FQDN, it's likely either host or domain + if {[string length $domain]} { + guessDomain $host.$domain + } else { + guessHost $host + } + } +} +catch close +wait + +###################################################################### +# ask NIC for any info about this host +###################################################################### + +if {$nic || ($d == 0)} { + vprint "talking to nic" + spawn telnet internic.net + expect { + -re $bad_telnet_responses { + telnet_error $expect_out(buffer) + } timeout { + vprint "timed out" + } "InterNIC >" { + send "whois\r" + expect "Whois: " + vprint "getting info on network $a.$b.$c" + send "net $a.$b.$c\r" + expect { + "No match*" { + vprint "no info" + expect "Whois: " + vprint "getting info on network $a.$b" + send "net $a.$b\r" + expect { + "No match*" { + vprint "no info" + } -re "net\r\n(\[^\r]*)\r" { + printhost $expect_out(1,string) nic 0 + } timeout { + vprint "timed out" + } + } + } -re "net\r\n(\[^\r]*)\r" { + printhost $expect_out(1,string) nic 0 + } timeout { + vprint "timed out" + } + } + } + } + catch close + wait + if {$d == 0} exit +} + +###################################################################### +# ask other hosts in the same class C what their name is +# so that we can at least get the likely domain +# +# do this in two loops - first from current IP address down to 0 +# and then next from current IP address up to 255 +###################################################################### + +# give up guessing host name +guessHost "unknown" + +for {set i [expr $d-1]} {$i>0} {incr i -1} { + vprint "talking smtp to $a.$b.$c.$i" + spawn telnet $a.$b.$c.$i smtp + expect { + -re $bad_telnet_responses { + telnet_error $expect_out(buffer) + } timeout { + vprint "timed out" + } -re "\n220 (\[^\\. ]*).?(\[^ ]*)" { + set host $expect_out(1,string) + set domain $expect_out(2,string) + printhost $guessHost.$domain "smtp - $a.$b.$c.$i is $host.$domain" 1 + + # if not valid FQDN, it's likely either host or domain + # don't bother recording host since it can't be for + # original addr. + if {[string length $domain]} { + guessDomain $host.$domain + } + } + } + catch close + wait +} + +for {set i [expr $d+1]} {$i<255} {incr i} { + vprint "talking smtp to $a.$b.$c.$i" + spawn telnet $a.$b.$c.$i smtp + expect { + -re $bad_telnet_responses { + telnet_error $expect_out(buffer) + } timeout { + vprint "timed out" + } -re "\n220 (\[^ ]*.(\[^ ])) " { + set host $expect_out(1,string) + set domain $expect_out(2,string) + printhost $guessHost.$domain "smtp - $a.$b.$c.$i is $host.$domain" 1 + + # if not valid FQDN, it's likely either host or domain + # don't bother recording host since it can't be for + # original addr. + if {[string length $domain]} { + guessDomain $host.$domain + } + } + } + catch close + wait +} + +###################################################################### +# print our best guess as to the name +###################################################################### + + +# How pathetic. Print something, anything! +if {!$verbose && !$tag} {send_user [guessFQDN]} |