chiark / gitweb /
Does re-mail-ck. About to profile
[vinegar-ip.git] / make-probes.tcl
index 2fb83be94e71cb576698dc23d33558bc6c3d2c6c..f41cae14986de7e989ba3904875a74c8c585f83e 100755 (executable)
@@ -18,9 +18,7 @@ proc manyset {list args} {
 
 proc start_gen {use_gen_counter} {
     global gen_counter rand_counter getlog_log rand_buf
-    set gen_counter $use_gen_counter
-    set rand_counter 0
-    set rand_buf {}
+    random-bytes-init $use_gen_counter
     set getlog_log {}
 }
 
@@ -35,28 +33,37 @@ proc packet-csum-ip {packet} {
     return [expr {$cs & 0xffff}]
 }
 
-set rand_buf {}
-proc random-bytes {n} {
-    global gen_counter rand_counter rand_buf
-    set n [expr {$n*2}]
-    set o {}
-    while {[set w [expr {$n - [string length $o]}]] > 0} {
-       if {![string length $rand_buf]} {
-           set md5 [exec md5sum << "$gen_counter $rand_counter"]
-           regexp {^[0-9a-f]{32}} $md5 rand_buf
-           if {![string length $rand_buf]} { error "?$md5?" }
-           incr rand_counter
+
+namespace eval Random-Bytes {
+    namespace export random-bytes random-bytes-init
+
+    proc random-bytes-init {seed} {
+       variable counter
+       variable fh
+       catch { set h $fh; unset fh; close $h }
+       set counter 0
+       set fh [open |[list openssl bf-ofb < /dev/zero -e -k " $seed"] r]
+       fconfigure $fh -translation binary
+    }
+    proc random-bytes {n} {
+       variable fh
+       set x [read $fh $n]
+       if {[string length $x] != $n} {
+           set h $fh; unset fh; close $h
+           error "openssl bf-ofb exited unexpectedly"
        }
-       append o [string range $rand_buf 0 [expr {$w-1}]]
-       set rand_buf [string range $rand_buf $w end]
+       binary scan $x H* y
+       if {[string length $y] != $n*2} { error "binary format failed $n $y" }
+       return $y
     }
-    return $o
 }
 
+namespace import Random-Bytes::*
+
 proc choice-int {min max} {
     set rv 0x[random-bytes 3]
     return [expr {
-       int( double($rv) / double(0xffffff) * double($max+1-$min) )
+       int( double($rv) / double(0x1000000) * double($max+1-$min) )
        + $min
     }]
 }
@@ -67,6 +74,19 @@ proc choice-prob {cv def} {
     return [expr {$rv < double($prob)*0x1000000}]
 }
 
+proc choice-mult {args} {
+    if {!([llength $args] % 2)} { error "choice-mult must have default" }
+    set x 0x[random-bytes 3]
+    set x [expr { double($x) / double(0x1000000) }]
+    set cump 0.0
+    set def [lindex $args end]
+    set args [lreplace $args end end]
+    foreach {val p} $args {
+       set cump [expr {$cump + double($p)}]
+       if {$x < $cump} { return $val }
+    }
+    return $def
+}
 
 proc getlog {msg} {
     upvar #0 getlog_log log
@@ -98,7 +118,7 @@ proc depending-on {scope enum_and_var mtu mtuadjust args} {
        # half the time random
        getlog (junk)
        get-for $scope-fill
-       get data randupto $mtu
+       get data rand 0 $mtu
        return $data
     } else {
        uplevel 1 [list $procname] $mtu $args
@@ -133,14 +153,8 @@ proc get-config {variable def kind args} {
     set var [eval [list get-config/$kind $val] $args]
 }
 
-proc get/enum {s v min max} {
-    if {[choice-prob $s-$v-unknown 0.5]} {
-       set rv [choice-int $min $max]
-    } else {
-       upvar #0 enum/val2name/$s-$v v2n
-       set rv [choice-int 1 [array size v2n]]
-       set rv [lindex [array names v2n] [expr {$rv-1}]]
-    }
+proc get-enum-got {s v rv} {
+    upvar #0 enum/val2name/$s-$v v2n
     if {[info exists v2n($rv)]} {
        getlog "$v=$v2n($rv)\[$rv]"
     } else {
@@ -149,6 +163,28 @@ proc get/enum {s v min max} {
     return $rv
 }
 
+proc get/enum-rand {s v min max} {
+    set rv [choice-int $min $max]
+    return [get-enum-got $s $v $rv]
+}
+
+proc get/enum-def {s v} {
+    upvar #0 enum/val2name/$s-$v v2n
+    set rv [choice-int 1 [array size v2n]]
+    set rv [lindex [array names v2n] [expr {$rv-1}]]
+    return [get-enum-got $s $v $rv]
+}
+
+proc get/enum {s v min max prand} {
+    get-for $s-$v
+    get any choice $prand
+    if {$any} {
+       return [get/enum-rand $s $v $min $max]
+    } else {
+       return [get/enum-def $s $v]
+    }
+}
+
 proc get/number {s v min max} {
     set rv [choice-int $min $max]
     getlog "$v=$rv"
@@ -167,9 +203,9 @@ proc get/choice {s v defprob} {
     return $rv
 }
 
-proc get/randupto {s v maxlen} {
+proc get/rand {s v minlen maxlen} {
     get-for $s-$v
-    get l number 0 $maxlen
+    get l number $minlen $maxlen
     return [random-bytes $l]
 }
 
@@ -186,13 +222,31 @@ proc get/v4addr {s v} {
     for {set i 0} {$i<4} {incr i} {
        set b [random-bytes 1]
        append rv $b
-       append p $d [format %d $b]
+       append p $d [format %d 0x$b]
        set d .
     }
     getlog "$v=$p"
     return $rv
 }
 
+proc get/choice-mult {s v args} {
+    set rv [eval choice-mult $args]
+    getlog "($rv)"
+    return $rv
+}
+
+proc get/string {s v minlen maxlen first rest} {
+    set o {}
+    set now $first
+    for {set l [choice-int $minlen $maxlen]} {$l>0} {incr l -1} {
+       set cn [choice-int 0 [expr {[string length $now]-1}]]
+       append o [string index $now $cn]
+       set now $rest
+    }
+    getlog "$v=\"$o\""
+    return $o
+}
+
 
 proc assemble {outvarname format} {
     # format should look like those RFC diagrams.
@@ -312,22 +366,30 @@ proc assembly-overwrite {outvarname location value} {
     if {$bitlen < 32 && $value >= (1<<$bitlen)} {
        error "$diag $value >= 2**$bitlen"
     }
-    while {$bitlen > 0} {
-       set byteno [expr {$bit1 / 8}]
-       set char0no [expr {$byteno*2}]
-       set char1no [expr {$char0no+1}]
-       set bytebit [expr {128>>($bit1 % 8)}]
-       set byte 0x[string range $out $char0no $char1no]
-       debug 7 "< $bit1+$bitlen $byteno $char0no $bytebit $byte $out"
-       set byte [expr {
-           ($value & (1<<($bitlen-1)))
-           ? ($byte | $bytebit)
-           : ($byte & ~$bytebit)
-       }]
-       set out [string replace $out $char0no $char1no [format %02x $byte]]
+    if {!($bit1 % 8) && !($bitlen % 8)} {
+       set char0no [expr {$bit1/4}]
+       set charlen [expr {$bitlen/4}]
+       set chareno [expr {$char0no + $charlen -1}]
+       set repl [format %0${charlen}x $value]
+       set out [string replace $out $char0no $chareno $repl]
+    } else {
+       while {$bitlen > 0} {
+           set byteno [expr {$bit1 / 8}]
+           set char0no [expr {$byteno*2}]
+           set char1no [expr {$char0no+1}]
+           set bytebit [expr {128>>($bit1 % 8)}]
+           set byte 0x[string range $out $char0no $char1no]
+           debug 7 "< $bit1+$bitlen $byteno $char0no $bytebit $byte $out"
+           set byte [expr {
+               ($value & (1<<($bitlen-1)))
+               ? ($byte | $bytebit)
+               : ($byte & ~$bytebit)
+           }]
+           set out [string replace $out $char0no $char1no [format %02x $byte]]
  debug 8 "> $bit1+$bitlen $byteno $char0no $bytebit 0x[format %02x $byte] $out"
-       incr bitlen -1
-       incr bit1
+           incr bitlen -1
+           incr bit1
+       }
     }
 }
 
@@ -350,7 +412,7 @@ proc gen_1_ip {mtu} {
        get frag number 0 0x1fff
     }
     get-config ttl 255 number 0 255
-    get proto enum 1 255
+    get proto enum 1 255 0.05
     get-config source 127.0.0.1 v4addr
     get-config dest 127.0.0.1 v4addr
     # we don't do any IP options
@@ -373,14 +435,14 @@ proc gen_1_ip {mtu} {
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     }
     assembly-overwrite ip ${?_header_checksum} [packet-csum-ip $ip]
-    append $ip $body
+    append ip $body
     return $ip
 }
 
 define ip-proto 1 icmp {mtu} {
     # RFC792
     get-for icmp
-    get type enum 0 255
+    get type enum 0 255 0.2
     manyset [depending-on icmp type $mtu -4] body code
     if {![string length $code]} { get code number 0 255 }
     set checksum 0
@@ -399,8 +461,8 @@ proc define-icmp-type-vanilla {num name} {
 }
 proc icmp-vanilla {mbl typename} {
     get-for icmp-$typename
-    get code enum 0 255
-    get body randupto $mbl
+    get code enum 0 255 0.4
+    get body rand 0 $mbl
     return [list $body $code]
 }
 
@@ -424,14 +486,14 @@ define icmp-sourcequench-code 0 quench {} {}
 
 define icmp-type 5 redirect {mbl} {
     get-for icmp-redirect
-    get code enum 0 255
+    get code enum 0 255 0.4
     get gateway v4addr
     assemble body {
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                 Gateway                                       |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     }
-    get data randupto [expr {$mbl-4}]
+    get data rand 0 [expr {$mbl-4}]
     append body $data
     return [list $body $code]
 }
@@ -445,7 +507,7 @@ define icmp-type 8 ping {mbl} { icmp-echo $mbl }
 define icmp-type 0 pong {mbl} { icmp-echo $mbl }
 proc icmp-echo {mbl} {
     get-for icmp-echo
-    get code enum 0 255
+    get code enum 0 255 0.4
     get id number 0 0xffff
     get seq number 0 0xffff
     assemble body {
@@ -453,7 +515,7 @@ proc icmp-echo {mbl} {
    |       Id                      |        Seq                    |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     }
-    get data randupto [expr {$mbl-8}]
+    get data rand 0 [expr {$mbl-8}]
     append body $data
     return [list $body $code]
 }
@@ -463,7 +525,7 @@ define icmp-type 13 timestamp {mbl} { icmp-timestamp }
 define icmp-type 14 timestampreply {mbl} { icmp-timestamp }
 proc icmp-timestamp {} {
     get-for icmp-timestamp
-    get code enum 0 255
+    get code enum 0 255 0.4
     get id number 0 0xffff
     get seq number 0 0xffff
     get originate ip-timestamp
@@ -488,7 +550,7 @@ define icmp-type 15 inforequest {mbl} { icmp-inforeq }
 define icmp-type 16 inforeply {mbl} { icmp-inforeq }
 proc icmp-inforeq {} {
     get-for icmp-inforeq
-    get code enum 0 255
+    get code enum 0 255 0.4
     get id number 0 0xffff
     get seq number 0 0xffff
     assemble body {
@@ -503,11 +565,45 @@ define icmp-inforeq-code 0 timestamp {} {}
 # MAYADD ICMP traceroute RFC1393
 # MAYADD ICMP router discovery RFC1256
 
+proc port_pair_data {scope mtu mtuadjust} {
+    get-for $scope
+
+    get style choice-mult \
+           request 0.24 \
+           reply 0.24 \
+           random 0.16 \
+           servers
+
+    if {"$style" != "random"} {
+       get port enum-def
+       set def_port $port
+    }
+    if {"$style" != "servers"} {
+       get port enum-rand 0 0xffff
+       set rand_port $port
+    }
+    switch -exact $style {
+       random  { set source_port $rand_port; set dest_port $rand_port }
+       request { set source_port $rand_port; set dest_port $def_port }
+       reply   { set source_port $def_port;  set dest_port $rand_port }
+       servers { set source_port $def_port;  set dest_port $def_port }
+    }
+    if {"$style" != "random"} {
+       set port $def_port
+       set data [depending-on $scope port $mtu $mtuadjust $style]
+    } else {
+       get data rand 0 [expr {$mtu + $mtuadjust}]
+    }
+    return [list $source_port $dest_port $data]
+}
+
 define ip-proto 17 udp {mtu} {
     get-for udp
-    set dest_port 4321
-    get source_port number 0 0xffff
-    get data randupto [expr {$mtu-8}]
+    get checksum choice-mult \
+           checksum_bad 0.20 \
+           checksum_none 0.20 \
+           checksum_good
+    manyset [port_pair_data udp $mtu 8] source_port dest_port data
     set length [packet-len $data]
     set checksum 0
     assemble udp {
@@ -518,16 +614,110 @@ define ip-proto 17 udp {mtu} {
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     }
     append udp $data
-    get checksum choice 0.75
-    if {$checksum} {
+    if {"$checksum" != "none"} {
        set csum [packet-csum-ip $udp]
        if {!$csum} { set csum 0xffff }
+       if {"$checksum" == "bad"} {
+           get error number 1 0xffff
+           set csum [expr {$csum ^ $error}]
+       }
     } else {
        set csum 0
     }
     assembly-overwrite udp ${?_checksum} $csum
 }
 
+define udp-port 50 remailck {mtu style} {
+    get-for remailck
+    if {"$style" == "request"} {
+       get what choice-mult \
+               req-baduser 0.15 \
+               req-auth 0.15 \
+               resp-ok 0.15 \
+               resp-auth 0.15 \
+               req-user
+    } else {
+       get what choice-mult \
+               req-baduser 0.15 \
+               req-auth 0.15 \
+               resp-auth 0.15 \
+               req-user 0.15 \
+               resp-ok
+    }
+    switch -exact $what {
+       req-user {
+           set auth 0
+           get user string 1 8 \
+                   abcdefghijklmnopqrustuvwxyz \
+                   abcdefghijklmnopqrustuvwxyz-0123456789_
+       }
+       req-baduser {
+           set auth 0
+           get user rand 0 [expr {$mtu - 4}]
+       }
+       req-auth {
+           get auth enum 0 31
+           set user [depending-on auth {$mtu - 4}]
+       }
+       resp-auth {
+           get auth number 0 0xffff
+           set modified 0
+           set read 0
+       }
+       resp-ok {
+           get mail choice-mult \
+                   newmail 0.15 \
+                   oldmail 0.15 \
+                   nomail 0.20 \
+                   times
+           set auth 0
+           switch -exact $mail {
+               newmail {
+                   set modified 0
+                   set read 1
+               }
+               oldmail {
+                   set modified 1
+                   set read 0
+               }
+               nomail {
+                   set modified 0
+                   set read 0
+               }
+               times {
+                   get modified number 1 600
+                   get read number 1 600
+               }
+               default { error "mail? $mail" }
+           }
+       }
+       default { error "what? $what" }
+    }
+    switch -glob $what {
+       req-* {
+            assemble packet {
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |         Auth                                                  |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+            }
+           append packet $user
+       }
+       resp-* {
+           assemble packet {
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |         Auth                                                  |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |         Modified                                              |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |         Read                                                  |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+            }
+       }
+       default { error "what?? $what" }
+    }
+    return $packet
+}
+
 proc emit {count} {
     global getlog_log errorInfo
     if {[catch {