aboutsummaryrefslogtreecommitdiff
path: root/rex
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2013-04-18 11:51:39 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2013-04-18 11:51:39 +0300
commit6b4a20c57705b325292a0a6de405d57b5f354bb4 (patch)
tree564ecc2612475e5ad4d1f9e24a2a78d44c1738c1 /rex
parent936bab2bed33ab383636b252857eb61245208446 (diff)
downloadrex-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-xrex145
1 files changed, 136 insertions, 9 deletions
diff --git a/rex b/rex
index 549d2a8..373ec4a 100755
--- a/rex
+++ b/rex
@@ -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

Return to:

Send suggestions and report system problems to the System administrator.