chiark / gitweb /
566757c75d4cd87b077fe76b8a4879b96545cf11
[secnet.git] / stest / common.tcl
1 source test-common.tcl
2
3 package require Tclx
4
5 load chiark_tcl_hbytes-1.so
6 load chiark_tcl_dgram-1.so
7
8 set netlink(inside) {
9     local-address "172.18.232.9";
10     secnet-address "172.18.232.10";
11     remote-networks "172.18.232.0/28";
12 }
13 set netlink(outside) {
14     local-address "172.18.232.1";
15     secnet-address "172.18.232.2";
16     remote-networks "172.18.232.0/28";
17 }
18
19 set ports(inside) {16913 16910}
20 set ports(outside) 16900
21
22 set extra(inside) {
23     local-mobile True;
24     mtu-target 1260;
25 }
26 set extra(outside) {}
27
28 proc mkconf {location site} {
29     global tmp
30     global builddir
31     global netlink
32     global ports
33     global extra
34     global netlinkfh
35     set pipefp $tmp/$site.netlink
36     foreach tr {t r} {
37         file delete $pipefp.$tr
38         exec mkfifo -m600 $pipefp.$tr
39         set netlinkfh($site.$tr) [set fh [open $pipefp.$tr r+]]
40         fconfigure $fh -blocking 0 -buffering none -translation binary
41     }
42     fileevent $netlinkfh($site.r) readable \
43         [list netlink-readable $location $site]
44     set fakeuf $tmp/$site.fake-userv
45     set fakeuh [open $fakeuf w 0755]
46     puts $fakeuh "#!/bin/sh
47 set -e
48 exec 3<&0
49 cat <&3 3<&- >$pipefp.r &
50 exec 3<>$pipefp.t
51 exec <$pipefp.t
52 exec 3<&-
53 exec cat
54 "
55     close $fakeuh
56     set cfg "
57         netlink userv-ipif {
58             name \"netlink\";
59             userv-path \"$fakeuf\";
60         $netlink($site)
61             mtu 1400;
62             buffer sysbuffer(2048);
63             interface \"secnet-test-[string range $site 0 0]\";
64         };
65         comm
66 "
67     set delim {}
68     foreach port $ports($site) {
69         append cfg "$delim
70             udp {
71                 port $port;
72                 address \"::1\", \"127.0.0.1\";
73                 buffer sysbuffer(4096);
74             }
75         "
76         set delim ,
77     }
78     append cfg ";
79         local-name \"test-example/$location/$site\";
80         local-key rsa-private(\"$builddir/test-example/$site.key\");
81 "
82     append cfg $extra($site)
83     append cfg "
84         log logfile {
85             prefix \"$site\";
86             class \"debug\",\"info\",\"notice\",\"warning\",\"error\",\"security\",\"fatal\";
87         };
88     "
89     append cfg {
90         system {
91         };
92         resolver adns {
93         };
94         log-events "all";
95         random randomfile("/dev/urandom",no);
96         transform eax-serpent { }, serpent256-cbc { };
97     }
98
99     set f [open $builddir/test-example/sites.conf r]
100     set sites [read $f]
101     close $f
102     append cfg $sites
103     append cfg {
104         sites map(site,all-sites);
105     }
106     return $cfg
107 }
108
109 proc spawn-secnet {location site} {
110     global tmp
111     global builddir
112     global netlinkfh
113     global env
114     global pidmap
115     global readbuf
116     upvar #0 pids($site) pid
117     set readbuf($site) {}
118     set cf $tmp/$site.conf
119     set ch [open $cf w]
120     puts $ch [mkconf $location $site]
121     close $ch
122     set argl [list $builddir/secnet -dvnc $cf]
123     set divertk SECNET_STEST_DIVERT_$site
124     puts -nonewline "spawn"
125     foreach k [array names env] {
126         switch -glob $k {
127             SECNET_STEST_DIVERT_* -
128             SECNET_TEST_BUILDDIR { }
129             *SECNET* -
130             *PRELOAD* { puts -nonewline " $k=$env($k)" }
131         }
132     }
133     puts " $argl"
134     if {[info exists env($divertk)]} {
135         switch -glob $env($divertk) {
136             i {
137                 puts -nonewline "run ^ command, hit return "
138                 flush stdout
139                 gets stdin
140                 set argl {}
141             }
142             0 - "" {
143             }
144             * {
145                 set argl [split $env($divertk)]
146             }
147         }
148     }
149     if {[llength $argl]} { 
150         set pid [fork]
151         set pidmap($pid) "secnet $location/$site"
152         if {!$pid} {
153             execl [lindex $argl 0] [lrange $argl 1 end]
154         }
155     }
156     puts -nonewline $netlinkfh($site.t) [hbytes h2raw c0]
157 }
158
159 proc netlink-readable {location site} {
160     global ok
161     upvar #0 readbuf($site) buf
162     upvar #0 netlinkfh($site.r) fh
163     while 1 {
164         set x [read $fh]
165         set h [hbytes raw2h $x]
166         if {![hbytes length $h]} return
167         append buf $h
168         #puts "READABLE $site buf=$buf"
169         while {[regexp {^((?:..)*?)c0(.*)$} $buf dummy now buf]} {
170             #puts "READABLE $site now=$now (buf=$buf)"
171             regsub -all {^((?:..)*?)dbdc} $now {\1c0} now
172             regsub -all {^((?:..)*?)dbdd} $now {\1db} now
173             puts "netlink-got-packet $location $site $now"
174             netlink-got-packet $location $site $now
175         }
176     }
177 }
178
179 proc netlink-got-packet {location site data} {
180     if {![hbytes length $data]} return 
181     switch -exact $site {
182         inside {
183             puts OK
184             finish 0
185         }
186         outside {
187             error "inside rx'd!"
188         }
189     }
190 }
191
192 proc bgerror {message} {
193     global errorInfo errorCode
194     catch {
195         puts stderr "
196 ----------------------------------------
197 $errorInfo
198
199 $errorCode
200 $message
201 ----------------------------------------
202     "
203     }
204     finish 1
205 }
206
207 proc sendpkt {} {
208     global netlinkfh
209     set p {
210         4500 0054 ed9d 4000 4001 24da ac12 e809
211         ac12 e802 0800 1de4 2d96 0001 f1d4 a05d
212         0000 0000 507f 0b00 0000 0000 1011 1213
213         1415 1617 1819 1a1b 1c1d 1e1f 2021 2223
214         2425 2627 2829 2a2b 2c2d 2e2f 3031 3233
215         3435 3637
216     }
217     puts -nonewline $netlinkfh(inside.t) \
218         [hbytes h2raw c0[join $p ""]c0]
219 }
220
221 set socktmp $tmp/s
222 exec mkdir -p -m700 $socktmp
223 regsub {^(?!/|\./)} $socktmp {./} socktmp ;# dgram-socket wants ./ or /
224
225 proc prefix_preload {lib} { prefix_some_path LD_PRELOAD $lib }
226
227 set env(UDP_PRELOAD_DIR) $socktmp
228 prefix_preload $builddir/stest/udp-preload.so
229
230 proc finish {estatus} {
231     puts stderr "FINISHING $estatus"
232     signal default SIGCHLD
233     global pidmap
234     foreach pid [array names pidmap] {
235         kill KILL $pid
236     }
237     exit $estatus
238 }
239
240 proc reap {} {
241     global pidmap
242     #puts stderr REAPING
243     foreach pid [array names pidmap] {
244         set got [wait -nohang $pid]
245         if {![llength $got]} continue
246         set info $pidmap($pid)
247         unset pidmap($pid)
248         puts stderr "reaped $info: $got"
249         finish 1
250     }
251 }
252
253 signal -restart trap SIGCHLD { after idle reap }
254
255 proc udp-proxy {} {
256     global socktmp udpsock
257     set u $socktmp/udp
258     file delete $u
259     regsub {^(?!/)} $u {./} u
260     set udpsock [dgram-socket create $u]
261     dgram-socket on-receive $udpsock udp-relay
262 }
263
264 proc udp-relay {data src sock args} {
265     global udpsock socktmp
266     set headerlen [expr {52+1}]
267     set orgsrc $src
268
269     set dst [hbytes range $data 0 $headerlen]
270     regsub {(?:00)*$} $dst {} dst
271     set dst [hbytes h2raw $dst]
272
273     hbytes overwrite data 0 [hbytes zeroes $headerlen]
274     regsub {.*/} $src {} src
275     set srch [hbytes raw2h $src]
276     hbytes append srch 00
277     if {[catch {
278         if {[regexp {[^.,:0-9a-f]} $dst c]} { error "bad dst" }
279         if {[hbytes length $srch] > $headerlen} { error "src addr too long" }
280         hbytes overwrite data 0 $srch
281         dgram-socket transmit $udpsock $data $socktmp/$dst
282     } emsg]} {
283         puts stderr "$orgsrc -> $dst: $emsg"
284     }
285 }
286
287 proc test-kex {} {
288     udp-proxy
289     spawn-secnet in inside
290     spawn-secnet out outside
291
292     after 500 sendpkt
293     after 1000 sendpkt
294     after 5000 timed-out
295
296     vwait ok
297 }