diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2013-04-18 11:51:39 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2013-04-18 11:51:39 +0300 |
commit | 6b4a20c57705b325292a0a6de405d57b5f354bb4 (patch) | |
tree | 564ecc2612475e5ad4d1f9e24a2a78d44c1738c1 /rex | |
parent | 936bab2bed33ab383636b252857eb61245208446 (diff) | |
download | rex-6b4a20c57705b325292a0a6de405d57b5f354bb4.tar.gz rex-6b4a20c57705b325292a0a6de405d57b5f354bb4.tar.bz2 |
Implement a DNS resolver.
* rex: Implement a simplistic DNS resolver. Use it when looking up
host-specific keys in the database.
* vpnc.exp (startvpnc): Ignore SIGHUP.
Diffstat (limited to 'rex')
-rwxr-xr-x | rex | 145 |
1 files changed, 136 insertions, 9 deletions
@@ -41,6 +41,106 @@ proc config_option {key} { return $config(option,$key) } +# ####################################################################### +# A poor man's resolver. Given the requirement of being as minimalistic +# as possible, I cannot use any external libraries. Therefore the task +# of resolving host names and IP addresses is handled by calling "host" +# and parsing its return. +# ####################################################################### + +namespace eval pmres { } + +proc ::pmres::hostorder {} { + global config + + if {![info exists config(hostorder)]} { + set config(hostorder) {files dns} + if {[catch {open "/etc/nsswitch.conf" "r"} fd] == 0} { + while {[gets $fd line] >= 0} { + if [regexp {[^[:space:]]*hosts:} "$line"] { + set config(hostorder) [lrange [regexp -all -inline {[^[:space:]]+} $line] 1 end] + break + } + } + close $fd + } + } + return $config(hostorder) +} + +proc ::pmres::files_match {mode arg var} { + upvar $var res + + if {[catch {open "/etc/hosts" "r"} fd] == 0} { + while {[gets $fd line] >= 0} { + regsub "#.*" $line "" rec + if {$rec == ""} { + continue + } + if {$mode == "-ip"} { + if {[lindex $rec 0] == $arg} { + eval lappend res [lrange $rec 1 end] + } + } else { + if {[lsearch -exact [lrange $rec 1 end] $arg] != -1} { + lappend res [lindex $rec 0] + } + } + } + close $fd + } +} + +proc ::pmres::dns_match {mode arg var} { + upvar $var res + + if {[catch [list exec host $arg] ans] == 0} { + foreach line [split $ans "\n"] { + if {$mode == "-ip"} { + if [regexp "domain name pointer" $line] { + regsub {\.$} [lindex $line 4] "" t + lappend res $t + } + } else { + if [regexp "has address" $line] { + lappend res [lindex $line 3] + } elseif [regexp "has IPv6 address" $line] { + lappend res [lindex $line 4] + } + } + } + } +} + +proc ::pmres::resolve {args} { + set mode [lindex $args 0] + if {$mode == "-host" || $mode == "-ip"} { + set arg [lindex $args 1] + } else { + set arg [lindex $args 0] + if {[regexp {\d+\.\d+\.\d+\.\d+} $arg]} { + set mode "-ip" + } elseif [regexp -nocase {(\d+)\.(\d+)\.(\d+)\.(\d+)\.in-addr.arpa} $arg o4 o3 o2 o1] { + set mode "-ip" + set arg "$o1.$o2.$o3.$o4" + } else { + set mode "-host" + } + } + set res {} + + foreach x [hostorder] { + set name "${x}_match" + if {[info procs "$name"] == "$name"} { + eval $name $mode $arg res + } + } + return $res +} + +# ####################################################################### +# Database access functions +# ####################################################################### # rexdbget KEY [KEY...] # Iterate over KEYs, find first of them that is defined and return its value. proc rexdbget {args} { @@ -49,12 +149,16 @@ proc rexdbget {args} { foreach key $args { if [info exist config(option,hostgroup)] { set x "$config(option,hostgroup):$key" + debug 3 "db: looking for $x" if {[info exist rexdb($x)]} { + debug 3 "db: found $x" return $rexdb($x) } } + debug 3 "db: looking for $key" if [info exist rexdb($key)] { + debug 3 "db: found $key" return $rexdb($key) } } @@ -95,6 +199,9 @@ proc rexdbclr {args} { set rexdb(updated) 1 } +# ####################################################################### +# Debugging and error reporting +# ####################################################################### proc debug {args} { global config @@ -114,6 +221,10 @@ proc terror {args} { send_error "$argv0: $msg\n" } +# ####################################################################### +# Various utility functions. +# ####################################################################### + # Compare two version numbers. Return 0 if they are the same, a negative # value if "a" is older than "b", and a positive value otherwise. proc vercmp {va vb} { @@ -242,6 +353,10 @@ proc getyn {args} { } } +# ####################################################################### +# Program-specific database functions. +# ####################################################################### + # Encrypt password proc passenc {pass} { binary scan [encoding convertto ebcdic $pass] H* enc @@ -401,10 +516,12 @@ proc editdb {dbname} { proc hostuser {host} { global config - set key "$host:user" - set val [rexdbget $key user] - if {$val != ""} { - return $val + foreach hk [concat $host [::pmres::resolve $host]] { + set key "$hk:user" + set val [rexdbget $key user] + if {$val != ""} { + return $val + } } if [config_option interactive] { @@ -432,12 +549,14 @@ proc hostuser {host} { proc hostpass {host} { global rexdb config - set key "$host:pass" - set val [rexdbget $key pass] - if {$val != ""} { - return [passdec $val] + foreach hk [concat $host [::pmres::resolve $host]] { + set key "$hk:pass" + set val [rexdbget $key pass] + if {$val != ""} { + return [passdec $val] + } } - + if [config_option interactive] { set x [getans -echo "Password on $host:"] if {$x == ""} { @@ -490,6 +609,11 @@ proc listgroups {} { } } +# ####################################################################### +# A parser for GNU-style command line syntax. +# Almost compatible with getopt_long(3), excepting several quirks. +# ####################################################################### + # getopt [-progname name] [-longopts list] argc argv shortopts script proc getopt {args} { while 1 { @@ -691,6 +815,9 @@ proc getopt {args} { return 0 } +# ####################################################################### +# The game begins... +# ####################################################################### set shortopts "CcdeEig:HhlNp:Ss:u:x:Vw" set longopts { debug d |