1#!../expect -- 2# 3# gethostbyaddr a.b.c.d - translate an internet address to a FQDN, 4# guessing (a lot) if necessary. 5# Author: Don Libes, NIST 6# Version 4.0 7# Written: January 11, 1991 8# Last revised: March 21, 1996 9 10# By default, return a FQDN (fully qualified domain name) or descriptive 11# string (if FQDN is not easily determinable). This is tagged with a brief 12# explanation of how it was determined. 13# 14# If the host part of the FQDN cannot be determined, the original IP address 15# is used. 16# 17# Optional arguments act as toggles: Default 18# -t tag names with a description of how derived. true 19# -v verbose. false 20# -r reverse names to see if they resolve back to orig IP address. true 21# -n query nic for a descriptive string if it begins to look like true 22# the FQDN may be hard to derive. 23# -d turn on debugging to expose underlying dialogue false 24# 25# These options and others (see below) may be set in a ~/.gethostbyaddr file 26# To set options from that file, use the same syntax as below. 27set timeout 120 ;# timeout query after this many seconds 28set tag 1 ;# same as -t 29set reverse 1 ;# same as -r 30set verbose 0 ;# same as -v 31set nic 1 ;# same as -n 32set debug 0 ;# same as -d 33log_user 0 34 35proc usage {} { 36 send_user "usage: gethostbyaddr \[options\] a.b.c.d\n" 37 send_user "options meaning (all options act as toggles) default\n" 38 send_user " -t tag with derivation description true\n" 39 send_user " -v verbose false\n" 40 send_user " -r reverse back to IP addr for verification true\n" 41 send_user " -n query nic true\n" 42 send_user " -d produce debugging output false\n" 43 send_user "options must be separate.\n" 44 exit 45} 46 47if {[file readable ~/.gethostbyaddr]} {source ~/.gethostbyaddr} 48 49while {[llength $argv]>0} { 50 set flag [lindex $argv 0] 51 switch -- $flag \ 52 "-v" { 53 set verbose [expr !$verbose] 54 set argv [lrange $argv 1 end] 55 } "-r" { 56 set reverse [expr !$reverse] 57 set argv [lrange $argv 1 end] 58 } "-n" { 59 set nic [expr !$nic] 60 set argv [lrange $argv 1 end] 61 } "-t" { 62 set tag [expr !$tag] 63 set argv [lrange $argv 1 end] 64 } "-d" { 65 set debug [expr !$debug] 66 set argv [lrange $argv 1 end] 67 debug $debug 68 } default { 69 break 70 } 71} 72 73set IPaddress $argv 74 75if {[llength $argv]!=1} usage 76if {4!=[scan $IPaddress "%d.%d.%d.%d" a b c d]} usage 77 78proc vprint {s} { 79 global verbose 80 81 if {!$verbose} return 82 send_user $s\n 83} 84 85# dn==1 if domain name, 0 if text (from nic) 86proc printhost {name how dn} { 87 global reverse tag IPaddress 88 89 if {$dn && $reverse} { 90 set verified [verify $name $IPaddress] 91 } else {set verified 0} 92 93 if {$verified || !$reverse || !$dn} { 94 if {$tag} { 95 send_user "$name ($how)\n" 96 } else { 97 send_user "$name\n" 98 } 99 100 if {$verified || !$reverse} { 101 close 102 wait 103 exit 104 } 105 } 106} 107 108# return 1 if name resolves to IP address 109proc verify {name IPaddress} { 110 vprint "verifying $name is $IPaddress" 111 set rc 0 112 spawn nslookup 113 expect ">*" 114 send $name\r 115 116 expect { 117 -re "\\*\\*\\* (\[^\r]*)\r" { 118 vprint $expect_out(1,string) 119 } timeout { 120 vprint "timed out" 121 } -re "Address:.*Address: (\[^\r]*)\r" { 122 set addr2 $expect_out(1,string) 123 if {[string match $IPaddress $addr2]} { 124 vprint "verified" 125 set rc 1 126 } else { 127 vprint "not verified - $name is $addr2" 128 } 129 } 130 } 131 close 132 wait 133 return $rc 134} 135 136set bad_telnet_responses "(telnet:|: unknown).*" 137 138proc telnet_error {s} { 139 regexp ": (.*)\r" $s dontcare msg 140 vprint $msg 141} 142 143proc guessHost {guess} { 144 global guessHost 145 if {[info exists guessHost]} return 146 set guessHost $guess 147} 148 149proc guessDomain {guess} { 150 global guessDomain 151 if {[info exists guessDomain]} return 152 set guessDomain $guess 153} 154 155proc guessFQDN {} { 156 global guessHost guessDomain 157 return $guessHost.$guessDomain 158} 159 160###################################################################### 161# first do a simple reverse nslookup 162###################################################################### 163 164vprint "using nslookup" 165spawn nslookup 166expect ">*" 167send "set query=ptr\r" 168expect ">*" 169send "$d.$c.$b.$a.in-addr.arpa\r" 170expect { 171 timeout { 172 vprint "timed out" 173 } -re "\\*\\*\\* (\[^\r]*)\r" { 174 vprint $expect_out(1,string) 175 } -re "name = (\[^\r]*)\r" { 176 set host $expect_out(1,string) 177 printhost $host nslookup 1 178 179 # split out hostname from FQDN as guess for later 180 guessHost [lindex [split $host "."] 0] 181 } 182} 183 184close 185wait 186 187###################################################################### 188# next telnet to host and ask it what its name is 189###################################################################### 190 191vprint "talking smtp to $IPaddress" 192spawn telnet $IPaddress smtp 193expect { 194 -re $bad_telnet_responses { 195 telnet_error $expect_out(buffer) 196 } timeout { 197 vprint "timed out" 198 } -re "\n220 (\[^\\. ]*).?(\[^ ]*)" { 199 set host $expect_out(1,string) 200 set domain $expect_out(2,string) 201 printhost $host.$domain smtp 1 202 203 # if not valid FQDN, it's likely either host or domain 204 if {[string length $domain]} { 205 guessDomain $host.$domain 206 } else { 207 guessHost $host 208 } 209 } 210} 211catch close 212wait 213 214###################################################################### 215# ask NIC for any info about this host 216###################################################################### 217 218if {$nic || ($d == 0)} { 219 vprint "talking to nic" 220 spawn telnet internic.net 221 expect { 222 -re $bad_telnet_responses { 223 telnet_error $expect_out(buffer) 224 } timeout { 225 vprint "timed out" 226 } "InterNIC >" { 227 send "whois\r" 228 expect "Whois: " 229 vprint "getting info on network $a.$b.$c" 230 send "net $a.$b.$c\r" 231 expect { 232 "No match*" { 233 vprint "no info" 234 expect "Whois: " 235 vprint "getting info on network $a.$b" 236 send "net $a.$b\r" 237 expect { 238 "No match*" { 239 vprint "no info" 240 } -re "net\r\n(\[^\r]*)\r" { 241 printhost $expect_out(1,string) nic 0 242 } timeout { 243 vprint "timed out" 244 } 245 } 246 } -re "net\r\n(\[^\r]*)\r" { 247 printhost $expect_out(1,string) nic 0 248 } timeout { 249 vprint "timed out" 250 } 251 } 252 } 253 } 254 catch close 255 wait 256 if {$d == 0} exit 257} 258 259###################################################################### 260# ask other hosts in the same class C what their name is 261# so that we can at least get the likely domain 262# 263# do this in two loops - first from current IP address down to 0 264# and then next from current IP address up to 255 265###################################################################### 266 267# give up guessing host name 268guessHost "unknown" 269 270for {set i [expr $d-1]} {$i>0} {incr i -1} { 271 vprint "talking smtp to $a.$b.$c.$i" 272 spawn telnet $a.$b.$c.$i smtp 273 expect { 274 -re $bad_telnet_responses { 275 telnet_error $expect_out(buffer) 276 } timeout { 277 vprint "timed out" 278 } -re "\n220 (\[^\\. ]*).?(\[^ ]*)" { 279 set host $expect_out(1,string) 280 set domain $expect_out(2,string) 281 printhost $guessHost.$domain "smtp - $a.$b.$c.$i is $host.$domain" 1 282 283 # if not valid FQDN, it's likely either host or domain 284 # don't bother recording host since it can't be for 285 # original addr. 286 if {[string length $domain]} { 287 guessDomain $host.$domain 288 } 289 } 290 } 291 catch close 292 wait 293} 294 295for {set i [expr $d+1]} {$i<255} {incr i} { 296 vprint "talking smtp to $a.$b.$c.$i" 297 spawn telnet $a.$b.$c.$i smtp 298 expect { 299 -re $bad_telnet_responses { 300 telnet_error $expect_out(buffer) 301 } timeout { 302 vprint "timed out" 303 } -re "\n220 (\[^ ]*.(\[^ ])) " { 304 set host $expect_out(1,string) 305 set domain $expect_out(2,string) 306 printhost $guessHost.$domain "smtp - $a.$b.$c.$i is $host.$domain" 1 307 308 # if not valid FQDN, it's likely either host or domain 309 # don't bother recording host since it can't be for 310 # original addr. 311 if {[string length $domain]} { 312 guessDomain $host.$domain 313 } 314 } 315 } 316 catch close 317 wait 318} 319 320###################################################################### 321# print our best guess as to the name 322###################################################################### 323 324 325# How pathetic. Print something, anything! 326if {!$verbose && !$tag} {send_user [guessFQDN]} 327