resolv.tcl
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 package require dns 1.0;
00023
00024 namespace ::resolv {
00025 variable version 1.0.3
00026 variable rcsid {$Id: resolv.tcl,v 1.9 2004/01/25 07:29:39 andreas_kupries Exp $}
00027
00028 namespace export resolve init ignore hostname
00029
00030 variable R
00031 if {![info exists R]} {
00032 array R = {
00033 initdone 0
00034 dns ""
00035 dnsdefault ""
00036 ourhost ""
00037 search {}
00038 }
00039 }
00040 }
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052 ret ::resolv::ignore ( type hostname ) {
00053 variable Cache
00054 catch {unset Cache($hostname)}
00055 return
00056 }
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071 ret ::resolv::init ( optional defaultdns ="" , optional search ={)} {
00072 variable R
00073 variable Cache
00074
00075 # Clean the resolver cache
00076 catch {unset Cache}
00077
00078
00079 R = (dnsdefault) $defaultdns
00080 R = (search) $search
00081
00082
00083
00084
00085
00086 res = [catch [list exec nslookup [info hostname]] lkup]
00087 if { $res == 0 } {
00088 l = [split $lkup]
00089 nl = ""
00090 foreach e $l {
00091 if { [string length $e] > 0 } {
00092 lappend nl $e
00093 }
00094 }
00095
00096
00097
00098
00099
00100
00101
00102 hostname = ""
00103 len = [llength $nl]
00104 for { i = 0 } { $i < $len } { incr i } {
00105 e = [lindex $nl $i]
00106 if { [string match -nocase "*server*" $e] } {
00107 hostname = [lindex $nl [expr {$i + 1}]]
00108 if { [string match -nocase "UnKnown" $hostname] } {
00109 hostname = ""
00110 }
00111 break
00112 }
00113 }
00114
00115 if { $hostname != "" } {
00116 R = (dns) $hostname
00117 } else {
00118 for { i = 0 } { $i < $len } { incr i } {
00119 e = [lindex $nl $i]
00120 if { [string match -nocase "*address*" $e] } {
00121 hostname = [lindex $nl [expr {$i + 1}]]
00122 break
00123 }
00124 }
00125 if { $hostname != "" } {
00126 R = (dns) $hostname
00127 }
00128 }
00129 }
00130
00131 if {$R(dns) == ""} {
00132 R = (dns) $R(dnsdefault)
00133 }
00134
00135
00136
00137 ourhost = ""
00138 if {$res == 0} {
00139 dot = [string first "." [info hostname]]
00140 if { $dot < 0 } {
00141 for { i = 0 } { $i < $len } { incr i } {
00142 e = [lindex $nl $i]
00143 if { [string match -nocase "*name*" $e] } {
00144 ourhost = [lindex $nl [expr {$i + 1}]]
00145 break
00146 }
00147 }
00148 if { $ourhost == "" } {
00149 if { ! [regexp {\d+\.\d+\.\d+\.\d+} $hostname] } {
00150 dot = [string first "." $hostname]
00151 ourhost = [format "%s%s" [info hostname] \
00152 [string range $hostname $dot end]]
00153 }
00154 }
00155 } else {
00156 ourhost = [info hostname]
00157 }
00158 }
00159
00160 if {$ourhost == ""} {
00161 R = (ourhost) [info hostname]
00162 } else {
00163 R = (ourhost) $ourhost
00164 }
00165
00166
00167 R = (initdone) 1
00168
00169 return $R(dns)
00170 }
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182 ret ::resolv::resolve ( type hostname ) {
00183 variable R
00184 variable Cache
00185
00186 # Initialise if not already done. Auto initialisation cannot take
00187 # any known DNS server (known to the caller)
00188 if { ! $R(initdone) } { init }
00189
00190 # Check whether this is not simply a raw IP address. What about
00191 # IPv6 ??
00192 # - We don't have sockets in Tcl for IPv6 protocols - [PT]
00193 #
00194 if { [regexp {\d+\.\d+\.\d+\.\d+} $hostname] } {
00195 return $hostname
00196 }
00197
00198 # Look for hostname in the cache, if found return.
00199 if { [array names ::resolv::Cache $hostname] != "" } {
00200 return $::resolv::Cache($hostname)
00201 }
00202
00203 # Scream if we don't have any DNS server setup, since we cannot do
00204 # anything in that case.
00205 if { $R(dns) == "" } {
00206 return -code error "No dns server provided"
00207 }
00208
00209 set R(retries) 0
00210 set ip [Resolve $hostname]
00211
00212 # And store the result of resolution in our cache for further use.
00213 set Cache($hostname) $ip
00214
00215 return $ip
00216 }
00217
00218 /* Description:*/
00219 /* Attempt to resolve hostname via DNS. If the name cannot be resolved then*/
00220 /* iterate through the search list appending each domain in turn until we*/
00221 /* get one that succeeds.*/
00222 /* */
00223 ret ::resolv::Resolve (type hostname) {
00224 variable R
00225 set t [::dns::resolve $hostname -server $R(dns)]
00226 ::dns::wait $t; # wait with event processing
00227 set status [dns::status $t]
00228 if {$status == "ok"} {
00229 set ip [lindex [::dns::address $t] 0]
00230 ::dns::cleanup $t
00231 } elseif {$status == "error"
00232 && [::dns::errorcode $t] == 3
00233 && $R(retries) < [llength $R(search)]} {
00234 ::dns::cleanup $t
00235 set suffix [lindex $R(search) $R(retries)]
00236 incr R(retries)
00237 set new [lindex [split $hostname .] 0].[string trim $suffix .]
00238 set ip [Resolve $new]
00239 } else {
00240 set err [dns::error $t]
00241 ::dns::cleanup $t
00242 return -code error "dns error: $err"
00243 }
00244 return $ip
00245 }
00246
00247 /* -------------------------------------------------------------------------*/
00248
00249 package provide resolv $::resolv::version
00250
00251 /* -------------------------------------------------------------------------*/
00252 /* Local Variables:*/
00253 /* indent-tabs-mode: nil*/
00254 /* End:*/
00255