source: tol/tolsh/tolsh.vfs/lib/tcllib1.10/dns/resolv.tcl @ 8597867d

1941-docker-image-to-testdevel
Last change on this file since 8597867d was 8597867d, checked in by Jorge Pérez <josp.jorge@…>, 16 years ago

closes #976, se incluye tcllib1.10, base64 debe eliminarse del raiz de lib ya que esta incluido en tcllib

git-svn-id: ​https://www.tol-project.org/svn/tolp/trunk@2556 be4846ae-f051-483a-831f-b64e7d08527f

  • Property mode set to 100644
File size: 7.8 KB
Line 
1# resolv.tcl - Copyright (c) 2002 Emmanuel Frecon <emmanuel@sics.se>
2#
3# Original Author --  Emmanuel Frecon - emmanuel@sics.se
4# Modified by Pat Thoyts <patthoyts@users.sourceforge.net>
5#
6#  A super module on top of the dns module for host name resolution.
7#  There are two services provided on top of the regular Tcl library:
8#  Firstly, this module attempts to automatically discover the default
9#  DNS server that is setup on the machine that it is run on.  This
10#  server will be used in all further host resolutions.  Secondly, this
11#  module offers a rudimentary cache.  The cache is rudimentary since it
12#  has no expiration on host name resolutions, but this is probably
13#  enough for short lived applications.
14#
15# -------------------------------------------------------------------------
16# See the file "license.terms" for information on usage and redistribution
17# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
18# -------------------------------------------------------------------------
19#
20# $Id: resolv.tcl,v 1.9 2004/01/25 07:29:39 andreas_kupries Exp $
21
22package require dns 1.0;                # tcllib 1.3
23
24namespace eval ::resolv {
25    variable version 1.0.3
26    variable rcsid {$Id: resolv.tcl,v 1.9 2004/01/25 07:29:39 andreas_kupries Exp $}
27
28    namespace export resolve init ignore hostname
29
30    variable R
31    if {![info exists R]} {
32        array set R {
33            initdone   0
34            dns        ""
35            dnsdefault ""
36            ourhost    ""
37            search     {}
38        }
39    }
40}
41
42# -------------------------------------------------------------------------
43# Command Name     --  ignore
44# Original Author  --  Emmanuel Frecon - emmanuel@sics.se
45#
46# Remove a host name resolution from the cache, if present, so that the
47# next resolution will query the DNS server again.
48#
49# Arguments:
50#    hostname   - Name of host to remove from the cache.
51#
52proc ::resolv::ignore { hostname } {
53    variable Cache
54    catch {unset Cache($hostname)}
55    return
56}
57
58# -------------------------------------------------------------------------
59# Command Name     --  init
60# Original Author  --  Emmanuel Frecon - emmanuel@sics.se
61#
62# Initialise this module with a known host name.  This host (not mandatory)
63# will become the default if the library was not able to find a DNS server.
64# This command can be called several times, its effect is double: actively
65# looking for the default DNS server setup on the running machine; and
66# emptying the host name resolution cache.
67#
68# Arguments:
69#    defaultdns - Default DNS server
70#
71proc ::resolv::init { {defaultdns ""} {search {}}} {
72    variable R
73    variable Cache
74
75    # Clean the resolver cache
76    catch {unset Cache}
77
78    # Record the default DNS server and search list.
79    set R(dnsdefault) $defaultdns
80    set R(search) $search
81
82    # Now do some intelligent lookup.  We do this on the current
83    # hostname to get a chance to get back some (full) information on
84    # ourselves.  A previous version was using 127.0.0.1, not sure
85    # what is best.
86    set res [catch [list exec nslookup [info hostname]] lkup]
87    if { $res == 0 } {
88        set l [split $lkup]
89        set nl ""
90        foreach e $l {
91            if { [string length $e] > 0 } {
92                lappend nl $e
93            }
94        }
95
96        # Now, a lot of mixture to arrange so that hostname points at the
97        # DNS server that we should use for any further request.  This
98        # code is complex, but was actually tested behind a firewall
99        # during the SITI Winter Conference 2003.  There, strangly,
100        # nslookup returned an error but a DNS server was actually setup
101        # correctly...
102        set hostname ""
103        set len [llength $nl]
104        for { set i 0 } { $i < $len } { incr i } {
105            set e [lindex $nl $i]
106            if { [string match -nocase "*server*" $e] } {
107                set hostname [lindex $nl [expr {$i + 1}]]
108                if { [string match -nocase "UnKnown" $hostname] } {
109                    set hostname ""
110                }
111                break
112            }
113        }
114
115        if { $hostname != "" } {
116            set R(dns) $hostname
117        } else {
118            for { set i 0 } { $i < $len } { incr i } {
119                set e [lindex $nl $i]
120                if { [string match -nocase "*address*" $e] } {
121                    set hostname [lindex $nl [expr {$i + 1}]]
122                    break
123                }
124            }
125            if { $hostname != "" } {
126                set R(dns) $hostname
127            }
128        }
129    }
130
131    if {$R(dns) == ""} {
132        set R(dns) $R(dnsdefault)
133    }
134
135
136    # Start again to find our full name
137    set ourhost ""
138    if {$res == 0} {
139        set dot [string first "." [info hostname]]
140        if { $dot < 0 } {
141            for { set i 0 } { $i < $len } { incr i } {
142                set e [lindex $nl $i]
143                if { [string match -nocase "*name*" $e] } {
144                    set ourhost [lindex $nl [expr {$i + 1}]]
145                    break
146                }
147            }
148            if { $ourhost == "" } {
149                if { ! [regexp {\d+\.\d+\.\d+\.\d+} $hostname] } {
150                    set dot [string first "." $hostname]
151                    set ourhost [format "%s%s" [info hostname] \
152                                     [string range $hostname $dot end]]
153                }
154            }
155        } else {
156            set ourhost [info hostname]
157        }
158    }
159
160    if {$ourhost == ""} {
161        set R(ourhost) [info hostname]
162    } else {
163        set R(ourhost) $ourhost
164    }
165
166
167    set R(initdone) 1
168
169    return $R(dns)
170}
171
172# -------------------------------------------------------------------------
173# Command Name     --  resolve
174# Original Author  --  Emmanuel Frecon - emmanuel@sics.se
175#
176# Resolve a host name to an IP address.  This is a wrapping procedure around
177# the basic services of the dns library.
178#
179# Arguments:
180#    hostname   - Name of host
181#
182proc ::resolv::resolve { hostname } {
183    variable R
184    variable Cache
185
186    # Initialise if not already done. Auto initialisation cannot take
187    # any known DNS server (known to the caller)
188    if { ! $R(initdone) } { init }
189
190    # Check whether this is not simply a raw IP address. What about
191    # IPv6 ??
192    # - We don't have sockets in Tcl for IPv6 protocols - [PT]
193    #
194    if { [regexp {\d+\.\d+\.\d+\.\d+} $hostname] } {
195        return $hostname
196    }
197
198    # Look for hostname in the cache, if found return.
199    if { [array names ::resolv::Cache $hostname] != "" } {
200        return $::resolv::Cache($hostname)
201    }
202
203    # Scream if we don't have any DNS server setup, since we cannot do
204    # anything in that case.
205    if { $R(dns) == "" } {
206        return -code error "No dns server provided"
207    }
208
209    set R(retries) 0
210    set ip [Resolve $hostname]
211
212    # And store the result of resolution in our cache for further use.
213    set Cache($hostname) $ip
214
215    return $ip
216}
217
218# Description:
219#  Attempt to resolve hostname via DNS. If the name cannot be resolved then
220#  iterate through the search list appending each domain in turn until we
221#  get one that succeeds.
222#
223proc ::resolv::Resolve {hostname} {
224    variable R
225    set t [::dns::resolve $hostname -server $R(dns)]
226    ::dns::wait $t;                       # wait with event processing
227    set status [dns::status $t]
228    if {$status == "ok"} {
229        set ip [lindex [::dns::address $t] 0]
230        ::dns::cleanup $t
231    } elseif {$status == "error"
232              && [::dns::errorcode $t] == 3
233              && $R(retries) < [llength $R(search)]} {
234        ::dns::cleanup $t
235        set suffix [lindex $R(search) $R(retries)]
236        incr R(retries)
237        set new [lindex [split $hostname .] 0].[string trim $suffix .]
238        set ip [Resolve $new]
239    } else {
240        set err [dns::error $t]
241        ::dns::cleanup $t
242        return -code error "dns error: $err"
243    }
244    return $ip
245}
246
247# -------------------------------------------------------------------------
248
249package provide resolv $::resolv::version
250
251# -------------------------------------------------------------------------
252# Local Variables:
253#   indent-tabs-mode: nil
254# End:
Note: See TracBrowser for help on using the repository browser.