- It does not offer any way to dynamically look for the default DNS setup on your machine.
- It does not offer any cache, which is not a very good idea, even though the DNS server is usually "close" to you.
[PT] 26Feb03: I have sucked this into tcllib as resolv package alongside the dns package. Some improvements to the resolution algorithm - like trying a search list of domain suffixes and ensuring that the dns request has completed using [dns::wait $token].
################## ## Module Name -- resolv.tcl ## Original Author -- Emmanuel Frecon - emmanuel@sics.se ## Description: ## ## A super module on top of the dns module for host name resolution. ## There are two services provided on top of the regular Tcl library: ## Firstly, this module attempts to automatically discover the default ## DNS server that is setup on the machine that it is run on. This ## server will be used in all further host resolutions. Secondly, this ## module offers a rudimentary cache. The cache is rudimentary since it ## has no expiration on host name resolutions, but this is probably ## enough for short lived applications. ## ################## package provide resolv 1.0 package require dns namespace eval ::resolv { namespace export resolve init ignore array set R { initdone 0 dns "" dnsdefault "" } } # Command Name -- ignore # Original Author -- Emmanuel Frecon - emmanuel@sics.se # # Remove a host name resolution from the cache, if present, so that the # next resolution will query the DNS server again. # # Arguments: # hostname - Name of host to remove from the cache. proc ::resolv::ignore { hostname } { global ::resolv::Cache catch "unset ::resolv::Cache($hostname)" } # Command Name -- init # Original Author -- Emmanuel Frecon - emmanuel@sics.se # # Initialise this module with a known host name. This host (not mandatory) # will become the default if the library was not able to find a DNS server. # This command can be called several times, its effect is double: actively # looking for the default DNS server setup on the running machine; and # emptying the host name resolution cache. # # Arguments: # defaultdns - Default DNS server proc ::resolv::init { { defaultdns "" } } { global ::resolv::R ::resolv::Cache catch "unset ::resolv::Cache" set ::resolv::R(dnsdefault) $defaultdns set res [catch "exec nslookup 127.0.0.1" lkup] if { $res == 0 } { set l [split $lkup] set nl "" foreach e $l { if { [string length $e] > 0 } { lappend nl $e } } set hostname "" set len [llength $nl] for { set i 0 } { $i < $len } { incr i } { set e [lindex $nl $i] if { [string match -nocase "*server*" $e] } { set hostname [lindex $nl [expr $i + 1]] break } } if { $hostname != "" } { set ::resolv::R(dns) $hostname } else { set ::resolv::R(dns) $::resolv::R(dnsdefault) } } set ::resolv::R(initdone) 1 return $::resolv::R(dns) } # Command Name -- resolve # Original Author -- Emmanuel Frecon - emmanuel@sics.se # # Resolve a host name to an IP address. This is a wrapping procedure around # the basic services of the dns library. # # Arguments: # hostname - Name of host proc ::resolv::resolve { hostname } { global ::resolv::R global ::resolv::Cache # Initialise if not already done. Auto initialisation cannot take # any known DNS server (known to the caller) if { ! $::resolv::R(initdone) } { ::resolv::init } # Check whether this is not simply a raw IP address. What about # IPv6 ?? if { [regexp "\\d+\\.\\d+\\.\\d+\\.\\d+" $hostname] } { return $hostname } # Look for hostname in the cache, if found return. if { [array names ::resolv::Cache $hostname] != "" } { return $::resolv::Cache($hostname) } # Scream if we don't have any DNS server setup, since we cannot do # anything in that case. if { $::resolv::R(dns) == "" } { error "No dns server provided" } # Now resolve in a clean way set t [::dns::resolve $hostname -server $::resolv::R(dns)] set ip [lindex [::dns::address $t] 0] ::dns::cleanup $t # And store the result of resolution in our cache for further use. set ::resolv::Cache($hostname) $ip return $ip }