chiark / gitweb /
test-common: Framework for compatibility tests
[secnet.git] / stest / common.tcl
index 0c1202ca378b3b34ed58820447a0a206a13ec628..89045a5147b5fb46206385be1c0afb8ab25bff91 100644 (file)
@@ -25,6 +25,11 @@ set extra(inside) {
 }
 set extra(outside) {}
 
+set privkey(inside) test-example/inside.privkeys/
+set privkey(outside) test-example/outside.privkeys/
+
+proc sitesconf_hook {l} { return $l }
+
 proc mkconf {location site} {
     global tmp
     global builddir
@@ -32,6 +37,7 @@ proc mkconf {location site} {
     global ports
     global extra
     global netlinkfh
+    upvar #0 privkey($site) privkey
     set pipefp $tmp/$site.netlink
     foreach tr {t r} {
        file delete $pipefp.$tr
@@ -54,6 +60,7 @@ exec cat
 "
     close $fakeuh
     set cfg "
+       hash sha1;
        netlink userv-ipif {
            name \"netlink\";
             userv-path \"$fakeuf\";
@@ -77,14 +84,33 @@ exec cat
     }
     append cfg ";
        local-name \"test-example/$location/$site\";
-       local-key rsa-private(\"$builddir/test-example/$site.key\");
 "
+    switch -glob $privkey {
+       */ {
+           set sitesconf sites.conf
+           append cfg "
+               key-cache priv-cache({
+                   privkeys \"$builddir/${privkey}priv.\";
+                });
+"
+       }
+       * {
+           set sitesconf sites-nonego.conf
+           append cfg "
+               local-key rsa-private(\"$builddir/$privkey\");
+"
+       }
+    }
+    set sitesconf $builddir/test-example/$sitesconf
+    
     append cfg $extra($site)
-    append cfg {
+    append cfg "
        log logfile {
-           filename "/dev/tty";
-           class "info","notice","warning","error","security","fatal";
+           prefix \"$site\";
+           class \"debug\",\"info\",\"notice\",\"warning\",\"error\",\"security\",\"fatal\";
        };
+    "
+    append cfg {
        system {
        };
        resolver adns {
@@ -94,13 +120,23 @@ exec cat
        transform eax-serpent { }, serpent256-cbc { };
     }
 
-    set f [open $builddir/test-example/sites.conf r]
+    set pubkeys $tmp/$site.pubkeys
+    file delete -force $pubkeys
+    exec cp -rl $builddir/test-example/pubkeys $pubkeys
+
+    set f [open $sitesconf r]
+    while {[gets $f l] >= 0} {
+       regsub {\"[^\"]*test-example/pubkeys/} $l "\"$pubkeys/" l
+       set l [sitesconf_hook $l]
+       append cfg $l "\n"
+    }
     set sites [read $f]
     close $f
     append cfg $sites
     append cfg {
        sites map(site,all-sites);
     }
+
     return $cfg
 }
 
@@ -108,28 +144,85 @@ proc spawn-secnet {location site} {
     global tmp
     global builddir
     global netlinkfh
+    global env
+    global pidmap
+    global readbuf
     upvar #0 pids($site) pid
+    set readbuf($site) {}
     set cf $tmp/$site.conf
     set ch [open $cf w]
     puts $ch [mkconf $location $site]
     close $ch
     set argl [list $builddir/secnet -dvnc $cf]
-    set pid [fork]
-    if {!$pid} {
-       execl [lindex $argl 0] [lrange $argl 1 end]
+    set divertk SECNET_STEST_DIVERT_$site
+    puts -nonewline "spawn"
+    foreach k [array names env] {
+       switch -glob $k {
+           SECNET_STEST_DIVERT_* -
+           SECNET_TEST_BUILDDIR - OLD_SECNET_DIR { }
+           *SECNET* -
+           *PRELOAD* { puts -nonewline " $k=$env($k)" }
+       }
+    }
+    puts " $argl"
+    if {[info exists env($divertk)]} {
+       switch -glob $env($divertk) {
+           i {
+               puts -nonewline "run ^ command, hit return "
+               flush stdout
+               gets stdin
+               set argl {}
+           }
+           0 - "" {
+           }
+           * {
+               set argl [split $env($divertk)]
+           }
+       }
+    }
+    if {[llength $argl]} { 
+       set pid [fork]
+       set pidmap($pid) "secnet $location/$site"
+       if {!$pid} {
+           execl [lindex $argl 0] [lrange $argl 1 end]
+       }
     }
     puts -nonewline $netlinkfh($site.t) [hbytes h2raw c0]
 }
 
 proc netlink-readable {location site} {
     global ok
+    upvar #0 readbuf($site) buf
     upvar #0 netlinkfh($site.r) fh
-    read $fh; # empty the buffer
+    while 1 {
+       set x [read $fh]
+       set h [hbytes raw2h $x]
+       if {![hbytes length $h]} return
+       append buf $h
+       #puts "READABLE $site buf=$buf"
+       while {[regexp {^((?:..)*?)c0(.*)$} $buf dummy now buf]} {
+           #puts "READABLE $site now=$now (buf=$buf)"
+           regsub -all {^((?:..)*?)dbdc} $now {\1c0} now
+           regsub -all {^((?:..)*?)dbdd} $now {\1db} now
+           puts "netlink-got-packet $location $site $now"
+           netlink-got-packet $location $site $now
+       }
+    }
+}
+
+proc netlink-got-packet {location site data} {
+    if {![hbytes length $data]} return 
     switch -exact $site {
        inside {
-           puts OK
-           set ok 1; # what a bodge
-           return
+           switch -glob $data {
+               45000054ed9d4000fe0166d9ac12e802ac12e80900* {
+                   puts "OK $data"
+                   finish 0
+               }
+               * {
+                   error "unexpected $site $data"
+               }
+           }
        }
        outside {
            error "inside rx'd!"
@@ -149,7 +242,7 @@ $message
 ----------------------------------------
     "
     }
-    exit 1
+    finish 1
 }
 
 proc sendpkt {} {
@@ -168,13 +261,38 @@ proc sendpkt {} {
 
 set socktmp $tmp/s
 exec mkdir -p -m700 $socktmp
-regsub {^(?!/)} $socktmp {./} socktmp ;# dgram-socket wants ./ or /
+regsub {^(?!/|\./)} $socktmp {./} socktmp ;# dgram-socket wants ./ or /
 
 proc prefix_preload {lib} { prefix_some_path LD_PRELOAD $lib }
 
 set env(UDP_PRELOAD_DIR) $socktmp
 prefix_preload $builddir/stest/udp-preload.so
 
+proc finish {estatus} {
+    puts stderr "FINISHING $estatus"
+    signal default SIGCHLD
+    global pidmap
+    foreach pid [array names pidmap] {
+       kill KILL $pid
+    }
+    exit $estatus
+}
+
+proc reap {} {
+    global pidmap
+    #puts stderr REAPING
+    foreach pid [array names pidmap] {
+       set got [wait -nohang $pid]
+       if {![llength $got]} continue
+       set info $pidmap($pid)
+       unset pidmap($pid)
+       puts stderr "reaped $info: $got"
+       finish 1
+    }
+}
+
+signal -restart trap SIGCHLD { after idle reap }
+
 proc udp-proxy {} {
     global socktmp udpsock
     set u $socktmp/udp