Hello, Here is a simple dns auditor, maps name -> ip and should work for other things scotty3 supports, BTW does any one have a patch to get the full SOA record back? The theory is simple you have 2 config files, list of dns servers to check and a csv file with 4 entries: dept tag, item to check, action, result. Ex: server_grp,www.xyz.com,address,123.123.123.123. What happens is that the check is preformed against each of the listed dns servers and checked for accuracy against the result. This is done by generating a tcl testsuite for the config files that you can execute at will. There are some ugly bits in it but it has proved useful. anyway here is the code: ====== #!/opt/pkg/bin/tclsh8.4 package require cmdline package require csv package require fileutil proc server_load { path file } { if {[catch {open $path/$file r} result]} { error "could not open file for reading : $result" } return [split [read $result ] \n] } proc items_load {path file} { set result [list] foreach line [server_load $path $file] { lappend result [csv::split $line ] } return $result } set options { {o.arg "out" "Change the default out file location"} {d.arg "data" "directory with data files"} {D.arg "servers" "DNS server info file"} {C.arg "check.csv" "Things to check file"} } set usage "{build|clean} \[options\] \n" ##::cmdline::getoptions argv $options $usage ## bug here with errors, probably my fault array set params [::cmdline::getoptions argv $options $usage ] #parray params #puts "$argv\n" set start " lappend auto_path /opt/local/lib package require Tnm package require tcltest namespace eval ::%s { namespace import ::tcltest::* namespace import ::Tnm::dns ## put dns server here format 'variable server ip' " set middle { test %s-%i.%i { %s: %s %s } -body { dns -server %s %s %s } -result %s } set end " cleanupTests } " set all.tcl { #!/opt/pkg/bin/tclsh8.4 package require tcltest ::tcltest::configure -testdir %s/%s eval ::tcltest::configure $argv ::tcltest::runAllTests } set tmp [server_load $params(d) $params(D) ] set servers [list] foreach line $tmp { if {[string length $line] >3 } { lappend servers $line } } set items [items_load $params(d) $params(C) ] set i 1 array set j {} foreach server $servers { #puts "server == $server\n" foreach row $items { if {[llength $row] < 2 } { continue } #puts "row:: $row\n" set owner [lindex $row 0] set item [lindex $row 1] set action [lindex $row 2] set result [lindex $row 3] if {[info exists bob($owner/$item)] != 1 } { set bob($owner/$item) [list] lappend bob($owner/$item) [format $start $item] #puts "$owner/$item new \n" set j($owner/$item) 1 } lappend bob($owner/$item) [format "$middle" $item $i $j($owner/$item)\ $server $action $item $server $action\ $item $result ] incr j($owner/$item) } incr i foreach name [array names j] { set j($name) 1 } } array set group_dir {} foreach row $items { if {[llength $row ] < 2 } { continue } set group_dir([lindex $row 0]) 1 } catch {exec rm -rf $params(o) } xxy #puts "$xxy" ::fileutil::writeFile $params(o)/all.tcl "[format ${all.tcl} [file dirname [file normalize [info script]]] $params(o) ]" foreach name [array names group_dir] { ::fileutil::writeFile $params(o)/$name/all.tcl "[format ${all.tcl} [file dirname [file normalize [info script]]] $params(o)/$name ]" } foreach name [array names bob] { lappend bob($name) [format $end] ::fileutil::writeFile $params(o)/$name.test "[join $bob($name) \n ]\n" # gets stdin } ====== Now if you have gotten here you can see there is room for improvement, comments welcome <> Networking