chiark / gitweb /
Including README and examples and stuff.
authorian <ian>
Sun, 3 Mar 2002 03:04:08 +0000 (03:04 +0000)
committerian <ian>
Sun, 3 Mar 2002 03:04:08 +0000 (03:04 +0000)
.cvsignore
Makefile
README [new file with mode: 0644]
lnumber-tcpdump.pl [new file with mode: 0755]
make-probes.tcl

index 0115f11acd992a596a36861dbe8f38fff7831197..2bfee31cf449132cd358676321e4316b2a72d692 100644 (file)
@@ -3,3 +3,6 @@ send-*.log
 send-*.pcap
 *.tmp
 on-dest.sh
 send-*.pcap
 *.tmp
 on-dest.sh
+recv-*.log
+recv-*.pcap
+recv-*.diff
index cf9c919d906e175ccd12c1d677ef6a9fd8e26b70..0ecd8284983655c12c6d2e74279e0fb6f89f9621 100644 (file)
--- a/Makefile
+++ b/Makefile
-# INSTRUCTIONS
+# Makefile for vinegar-ip
 #
 #
-# This is a tool for TCP transparency testing.  It allows you to send
-# a wide variety of `interesting' packets from one nominated machine
-# to another, and then examine what arrived to see if there are any
-# differences.
+# This file is part of vinegar-ip, tools for IP transparency testing.
+# vinegar-ip is Copyright (C) 2002 Ian Jackson
 #
 #
-# Up to 4 hosts are involved: one to do the test dataset generation, a
-# sender, a receiver, and one to do the analysis.
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
 #
 #
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
 #
 #
-# WHAT YOU WILL NEED
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
 #
 #
-#  on the machine you generate the test data
-#      This Makefile and corresponding Tcl script
-#      Tcl (as /usr/bin/tclsh)
-#      OpenSSL (as `openssl' on PATH)
-#      Lots of CPU !  (the generation script is rather slow)
-#
-#  on the sending machine
-#      tcpreplay (http://www.subterrain.net/tools/tcpreplay/,
-#              or from Debian testing 3.5.2002.  I used 1.0.1-1.1)
-#              and root privilege to run it
-#
-#  on the receiving machine
-#      tcpdump for packet capture, and root privilege to run it
-#      The `on-dest.sh' script that this Makefile creates
-#
-#  on the analysis machine
-#      tcpdump for converting trace files only, no root privilege
-#      This Makefile to drive tcpdump for you, if you like
-#      diff to look at the output
-#
-# It will be much better if the machines you are using do not have any
-# other traffic.  If they do the tests may disrupt it, and it'll get
-# in the way of your analysis too.
-#
-#
-# WHAT TO DO
-#
-#  1. Generate the test data.
-#      * Edit this Makefile.
-#          You /must/ change SOURCE and DEST; they must be IPv4 addresses.
-#          You may also change PARTS, PERPART or MTU if you like.
-#      * Say `make -j2 generate'.  This will generate the test data sets.
-#          This will take a while.  Vary the -j for your system.
-#      * Copy send-*.pcap and on-dest.sh to the sending machine.
-#
-#  2. Run one of the tests
-#      * Pick a PART number, say 1, to start with.
-#      * On the receiving machine, say, as root,
-#              ./on-dest.sh PART
-#          and leave it running.
-#      * On the sending machine, say, as root,
-#              tcpreplay -m 1 <send-PART.pcap
-#          The -m 1 option makes tcpreplay send the packets at one a
-#          second (they are generated as if they were captured at one
-#          a second); this avoids flooding the network, which causes
-#          congestion, packet loss and maybe other randomness.
-#          This will take (by default) 100 seconds.
-
-#
-#
-#
-# FILES INVOLVED
-#    Those made by `make generate':
-#      send-*.pcap     `pcap' format raw test data files
-#                       (feed this to tcpreplay -m 1)
-#      send-*.log      tcpdump's interpretation of the test data
-#                       with line numbers added
-#      send-*.why      The generator's explanations (ha ha) of
-#                       what the test data is
-#      on-dest.sh      Script for running tcpdump on the destination
-#
-#    Those supposedly captured at the destination
-#      recv-*.pcap     `pcap' format raw received packets
-#
-#    Those made during the analysis:
-#      recv-*.log      tcpdump's interpretation of the received packets
-#      recv-*.diff     difference between send-*.log and recv-*.log
-#      all.diff        all the .diff's concatenated in one easy file
-#
-#
-#  On the receiving machine,
-#      
-#
-#  on the 
-#  Run this makefile anywhere to generate the test data sets
-#  
+# $Id$
 
 
+#############################################################
+# You should edit the parameters below for your site
 
 SOURCE=                172.18.45.35
 
 SOURCE=                172.18.45.35
-DEST=          172.18.45.35
+DEST=          172.18.45.6
 
 UNIQUE=
 # set UNIQUE to something random for less observability
 
 
 UNIQUE=
 # set UNIQUE to something random for less observability
 
+# NB, this MTU is not completely strictly adhered to by the
+# test packet generator.  Sorry.
 MTU=           100
 
 # no of packets in each individual part, including part 1
 MTU=           100
 
 # no of packets in each individual part, including part 1
-PERPART=       10
+PERPART=       100
 
 
-# `rest' is made of PARTS-1 parts of PERPART packets
-PARTS=         10
+# REST is made of PARTS-1 parts of PERPART packets
+PARTS=         100
 
 # You shouldn't need to edit anything beyond this point.
 
 # You shouldn't need to edit anything beyond this point.
+#############################################################
 
 FEW_TARGETS=   on-dest.sh \
                send-1.pcap send-1.log send-1.why
 
 
 FEW_TARGETS=   on-dest.sh \
                send-1.pcap send-1.log send-1.why
 
-TARGETS=       $(GEN_SMALL) \
-               send-rest.pcap send-rest.log send-rest.why
+TARGETS=       $(FEW_TARGETS) \
+               send-all.pcap send-all.log send-all.why
 
 
-R_PARTNOS=     $(shell \
-       set -e; i=2; while [ $$i -le $(PARTS) ]; do \
+A_PARTNOS=     $(shell \
+       set -e; i=1; while [ $$i -le $(PARTS) ]; do \
                echo $$i; i=$$(( $$i + 1)); done \
        )
 
                echo $$i; i=$$(( $$i + 1)); done \
        )
 
-R_BASES=       $(addprefix send-,1 $(R_PARTNOS))
-R_PCAPS=       $(addsuffix .pcap,$(R_BASES))
-R_WHYS=                $(addsuffix .why,$(R_BASES))
+A_BASES=       $(addprefix send-,$(A_PARTNOS))
+A_PCAPS=       $(addsuffix .pcap,$(A_BASES))
+A_WHYS=                $(addsuffix .why,$(A_BASES))
+
+AN_BASES=      $(basename $(wildcard recv-*.pcap))
+AN_LOGS=       $(addsuffix .log,$(AN_BASES))
+AN_DIFFS=      $(addsuffix .diff,$(AN_BASES))
+AN_TARGETS=    $(AN_LOGS) $(AN_DIFFS)
+
+INFORM=                @echo ' GENERATED THESE FILES:'; \
+               echo '          $^'
 
 all:           $(TARGETS)
 
 all:           $(TARGETS)
+                       $(INFORM)
+
 few:           $(FEW_TARGETS)
 few:           $(FEW_TARGETS)
+                       $(INFORM)
+
+anal analyse:  $(AN_TARGETS)
+                       $(INFORM)
 
 
-send-rest.pcap:        $(R_PCAPS)
+send-all.pcap: $(A_PCAPS) Makefile
                rm -f $@
                dd if=$< ibs=24 count=1 of=$@
                rm -f $@
                dd if=$< ibs=24 count=1 of=$@
-               set -e; for f in $^; do \
+               set -e; for f in $(A_PCAPS); do \
                        dd ibs=24 skip=1 if=$$f >>$@; done
 
                        dd ibs=24 skip=1 if=$$f >>$@; done
 
-send-rest.why: $(R_WHYS)
-               cat $(R_WHYS) >$@.1.tmp
+send-all.why:  $(A_WHYS) Makefile
+               cat $(A_WHYS) >$@.1.tmp
                nl -bp'^ ? ? ?[0-9]' <$@.1.tmp >$@.2.tmp
                @mv -f $@.2.tmp $@
 
                nl -bp'^ ? ? ?[0-9]' <$@.1.tmp >$@.2.tmp
                @mv -f $@.2.tmp $@
 
-send-%.pcap:   ./make-probes.tcl
+send-%.pcap send-%.why:        ./make-probes.tcl Makefile
        ./make-probes.tcl --write $@ --mtu $(MTU) --upto $(PERPART) \
                --source $(SOURCE) --dest $(DEST) --xseed "$* $(UNIQUE)" \
                >send-$*.why
 
        ./make-probes.tcl --write $@ --mtu $(MTU) --upto $(PERPART) \
                --source $(SOURCE) --dest $(DEST) --xseed "$* $(UNIQUE)" \
                >send-$*.why
 
-%.log:         %.pcap
-               tcpdump -tnxvvs$$(($(MTU)+50)) -r $< >$@.1.tmp
-               nl -bp'^[0-9]' <$@.1.tmp >$@.2.tmp
+%.log:         %.pcap lnumber-tcpdump.pl Makefile
+               tcpdump -tnxvvs$$(($(MTU)+500)) -r $< >$@.1.tmp
+               ./lnumber-tcpdump.pl <$@.1.tmp >$@.2.tmp
                @mv -f $@.2.tmp $@
 
                @mv -f $@.2.tmp $@
 
+recv-%.diff:   send-%.log recv-%.log
+               diff -uI'^[0-9]' $^ >$@ || test $$? == 1
+
 on-dest.sh:    Makefile
        @rm -f $@
        echo >$@ "#!/bin/sh"
 on-dest.sh:    Makefile
        @rm -f $@
        echo >$@ "#!/bin/sh"
@@ -151,7 +104,7 @@ on-dest.sh: Makefile
        @echo >>$@ "#   ./on-dest.sh PART"
        @echo >>$@ "# where PART ranges from 1 to $(PARTS)"
        @echo >>$@ "if ! [ \$$# = 1 ]; then echo >&2 'PART?'; exit 1; fi"
        @echo >>$@ "#   ./on-dest.sh PART"
        @echo >>$@ "# where PART ranges from 1 to $(PARTS)"
        @echo >>$@ "if ! [ \$$# = 1 ]; then echo >&2 'PART?'; exit 1; fi"
-       @echo >>$@ "exec tcpdump -ps$$(($(MTU)+50)) -w recv-\$$1.pcap \\"
+       @echo >>$@ "exec tcpdump -s$$(($(MTU)+500)) -w recv-\$$1.pcap \\"
        @echo >>$@ " src host $(SOURCE) and dst host $(DEST)"
        chmod +x $@
 
        @echo >>$@ " src host $(SOURCE) and dst host $(DEST)"
        chmod +x $@
 
@@ -160,3 +113,5 @@ clean:
 
 realclean:     clean
                rm -f $(TARGETS) *.pcap *.why *.log
 
 realclean:     clean
                rm -f $(TARGETS) *.pcap *.why *.log
+
+# $Id$
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..cbcc94a
--- /dev/null
+++ b/README
@@ -0,0 +1,240 @@
+VINEGAR-IP - INSTRUCTIONS
+
+This is a tool for IP transparency testing.  It allows you to send a
+wide variety of `interesting' packets from one nominated machine to
+another, and then examine what arrived to see if there are any
+differences.
+
+Up to 3 hosts are involved: one to do the test dataset generation and
+analysis, as well as of course the sender and receiver.
+
+
+WHAT YOU WILL NEED
+
+* On the machine you generate and analyse the test data
+       This Makefile and corresponding scripts
+       GNU Make
+       Tcl (as /usr/bin/tclsh)
+       Perl (as /usr/bin/perl)
+       OpenSSL (as `openssl' on PATH)
+       tcpdump for converting trace files only, no root privilege
+       GNU diff to look at the output
+       Lots of CPU !  (the generation script is rather slow)
+
+* On the sending machine
+       tcpreplay (http://www.subterrain.net/tools/tcpreplay/,
+               or from Debian testing 3.5.2002.  I used 1.0.1-1.1)
+               and root privilege to run it
+
+* On the receiving machine
+       tcpdump for packet capture, and root privilege to run it
+       The `on-dest.sh' script that this Makefile creates
+
+It will be much better if the source and destination machines do not
+have any other traffic.  If they do the tests may disrupt it, and
+it'll get in the way of your analysis too.
+
+
+WHAT TO DO
+
+1. Generate the test data.
+       * Edit this Makefile.
+           You /must/ change SOURCE and DEST; they must be IPv4 addresses.
+           You may also change PARTS, PERPART or MTU if you like.
+       * Say `make -j2 all'.  This will generate the test data sets.
+           This will take a while.  Vary the -j for your system.
+           If you want to do a quick test first, you can say
+           `make few' first, instead.
+       * Copy send-1.pcap and send-all.pcap to the sending machine.
+       * Copy on-dest.sh to the to the receiving machine.
+
+2. Run the first, small test
+       * On the receiving machine, say, as root,
+               ./on-dest.sh 1
+           and leave it running.
+       * On the sending machine, say, as root,
+               tcpreplay -m 1 <send-1.pcap
+           The -m 1 option makes tcpreplay send the packets at one a
+           second (they are generated as if they were captured at one
+           a second); this avoids flooding the network, which causes
+           congestion, packet loss and maybe other randomness.
+           This will take (by default) 100 seconds.
+       * When it has finished, kill on-dest.sh.  Copy the
+           file recv-1.pcap back to your analysis machine, and
+           there say `make analyse' (or `make anal' if you prefer).
+       * This will generate `recv-1.log' and `recv-1.diff'.
+           Read the diff and see if it's by and large working.
+           See below for information about interpreting the various files.
+
+3. Run the full test
+       Do the same as step 2, but instead of `1', say `all'
+       everywhere.
+
+
+FILES INVOLVED
+   Those made by `make generate':
+       send-X.pcap     `pcap' format raw test data files
+                        (feed this to tcpreplay -m 1)
+       send-X.log      tcpdump's interpretation of the test data
+                        with line numbers added
+       send-X.why      The generator's explanations (ha ha) of
+                        what the test data is
+       on-dest.sh      Script for running tcpdump on the destination
+   You really want to be paying attention to the ones where
+   X is `1' and `all'.  The others, 2 onwards, are all in
+   `all' and it'll be easier to take them all at once.
+
+   Those supposedly captured at the destination
+       recv-X.pcap     `pcap' format raw received packets
+
+   Those made during the analysis:
+       recv-X.log      tcpdump's interpretation of the received packets
+       recv-X.diff     difference between send-*.log and recv-*.log
+
+
+INTERPRETATION OF THE TEXT FILES - EXAMPLE
+
+Here is an example of a diff you might see:
+
+@@ -23,12 +15,7 @@
+                         453e 001c f194 0000 ff02 17bf ac12 2d23
+                         ac12 2d06 1029 36f1 7daa 3b3b 0000 0000
+                         0000 0000 0000 0000 0000 0000 0000
+-5
+-    172.18.45.35 > 172.18.45.6: icmp: type-#75 (DF) [tos 0xe7] (ttl 255, id 30130)
+-                        45e7 0023 75b2 4000 ff01 52f2 ac12 2d23
+-                        ac12 2d06 4b8c 34ba 4844 ce2d 1bde 5caf
+-                        0ab9 e600 0000 0000 0000 0000 0000
+-6
++4
+     172.18.45.35.21814 > 172.18.45.6.21814: udp 12 (ttl 255, id 26421)
+                         4500 0028 6735 0000 ff11 a241 ac12 2d23
+
+This means that a packet which was sent, was not received.  You can
+see the actual hex contents, and tcpdump's interpretation, in the
+lines marked with `-'.  The changed numbers at the left are just the
+packet numbers.  You can use the numbers marked with `-' to find the
+corresponding packet in the other files.  Ignore the numbers marked
+with `+', they aren't useful.  In this case, it's packet 5 that's
+missing.  So, we can look in send-1.why or send-rest.why, as
+appropriate, and see this:
+
+   1 5  tos=0xe7 id=30130 df (!any) proto=icmp[1] \
+                 (any) type=75 (junk) l=11 code=140
+       45e7002375b24000ff0152f2ac122d23ac122d064b8c34ba4844ce2d1bde5caf0ab9e6
+
+In send-all.why, these are prepended by another line number, which is
+the one you should use, so it would look like this:
+
+     5     1 5  tos=0xe7 id=30130 df (!any) proto=icmp[1] \
+                         (any) type=75 (junk) l=11 code=140
+              45e7002375b24000ff0152f2ac122d23ac122d064b8c34ba4844ce2d\
+                                                         1bde5caf0ab9e6
+
+(The other two numbers are the batch and line within the batch.
+I have wrapped this here with \ and some indentation for ease of
+reading.)
+
+You can see the hex dump of the packet, which is the same as the one
+in the tcpdump output, except that the tcpdump one has some extra
+padding with zeroes to bring it to the minimum ethernet frame size.
+You can also see some notes that the generator made:
+
+  tos=0xe7 id=30130     The IP TOS and ID
+  df                    The Don't Fragment flag was set (there would
+                         be `frag' here if it was fragmented)
+  (!any)                It picked a known next layer up [`(!any)']
+  proto=icmp[1]          and the one it picked was protocol 1, icmp
+  (any) type=75         It picked an unknown next layer up, icmp type no.75
+  (junk) l=11            and gave it 11 bytes of junk payload
+  code=140               and an icmp code value of 140
+
+
+Some more examples from send-*.why and send-*.log files:
+
+    17     2 7  tos=0x14 id=56320 !df (!any) proto=tcp[6] source_port=37365 \
+                dest_port=52759 (connect) seq=0xab57703f ack=0x6c55ec70 \
+                window=0xdd21 !p u urg=0xce6c (noopt) (!optxpad) !unexpdata \
+                csumerror=0x9a18
+
+    172.18.45.35.37365 > 172.18.45.6.52759: S 2874634303:2874634303(0) \
+                      win 56609 urg 52844 [tos 0x14] (ttl 255, id 56320)
+
+This is a TCP SYN packet with urgent data, .  However, it has been
+generated with an invalid checksum: the checksum in the packet has
+been XOR'd with 0x9a18.
+
+    59     6 9  tos=0x2f id=15886 !df (!any) proto=tcp[6] source_port=52650 \
+                dest_port=37162 (data) seq=0xec912ceb ack=0x8cd28874 \
+                window=1 !p !u urg=0xe427 (badopt) l=30 l=12
+
+    172.18.45.35.52650 > 172.18.45.6.37162: . 3968937195:3968937207(12) \
+               ack 2362607732 win 1 <[bad opt]> [tos 0x2f] (ttl 255, id 15886)
+
+More TCP.  This time it's a data packet.  The urgent flag isn't set
+(though the urgent pointer value is nonzero), and it has 30 bytes of
+invalid option data and 12 bytes of actual data.
+
+   134    7 14  tos=0x4e id=12035 df (!any) proto=ip[4] \
+                source=206.78.180.32 dest=252.75.191.229 \
+                tos=0x94 id=14197 df (!any) proto=udp[17] (reply) \
+                port=remailck[50] port=20463 (resp-auth) auth=0xabcf
+
+    172.18.45.35 > 172.18.45.6: 206.78.180.32.50 > 252.75.191.229.20463: \
+                udp 12 (DF) [tos 0x94] (ttl 255, id 14197) (DF) \
+                [tos 0x4e] (ttl 255, id 12035)
+
+IPv4 tunnelling.  The outer packet has TOS 4e and ID 12035.  Both The
+inner packet is a reply from a UDP service `(reply)' from a well-known
+port to a random port.  The packet is according to the RFC1339 mail
+check service on port 50, requesting authorisation from the client;
+the server's authorisations' supported bitmap is allegedly 0xabcf.
+
+    15    1 15  tos=0x5b id=61344 df (!any) proto=udp[17] (random) \
+                port=20500 port=11701 l=2
+
+    172.18.45.35.20500 > 172.18.45.6.11701: udp 2 (DF) [tos 0x5b] \
+                (ttl 255, id 61344)
+
+This is a generic UDP packet from one random port (20500 in this case)
+to another (11701).  It has 2 bytes of data.
+
+    59    3 19  tos=0xa0 id=36385 !df (!any) proto=udp[17] (servers) \
+                port=dhcpserv[67] (!any) op=reply[2] (!any) htype=ethernet[1] \
+                hops=88 xid=0xd31e0dfe secs=149 flags=0x80 \
+                ciaddr=70.114.113.11 yiaddr=38.225.152.221 \
+                siaddr=98.91.71.52 giaddr=128.20.46.24 \
+                sname="yc3g27vvukig44qsx8lpud4e1.dbxxidju2ok3kipebqkd.pd2x\
+                89rdmrfz1dr" file="/o.h22gsn7s44yq2llx.v_-a+s_f421_iijnroam\
+                krpm7b674t7w.y3lfw8immrjaqpsu7.a.x.nev+j3hi/" (nocsum)
+
+This is a UDP packet between well-known ports `(servers)'; the
+generator only generates such packets with identical source and
+destination ports, in this case the DHCP server port.  (Usually DHCP
+servers would talk to clients, not to each oehter.)  There is a DHCP
+packet whose details you can see.  `(nocsum)' indicates that the UDP
+checksum field in the UDP header is set to 0, indicating that no
+checksum is to be performed.
+
+
+# This file is part of vinegar-ip, tools for IP transparency testing.
+# vinegar-ip is Copyright (C) 2002 Ian Jackson
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
+#
+# $Id$
+
+
+ $Id$
diff --git a/lnumber-tcpdump.pl b/lnumber-tcpdump.pl
new file mode 100755 (executable)
index 0000000..5c5f6c4
--- /dev/null
@@ -0,0 +1,3 @@
+#!/usr/bin/perl -p
+print ++$counter,"\n" or die $! if m/^ ?[^ \t]/;
+s/^/    /;
index 478fc3fc9b57bf59b6c92b8e252246d98eef500b..ce215a8dbf6addb0346003588c515c9718b29600 100755 (executable)
@@ -1,5 +1,25 @@
 #!/usr/bin/tclsh
 
 #!/usr/bin/tclsh
 
+# core packet generator for vinegar-ip
+#
+# This file is part of vinegar-ip, tools for IP transparency testing.
+# vinegar-ip is Copyright (C) 2002 Ian Jackson
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
+#
+# $Id$
 
 proc debug {level str} {
     global debug_level
 
 proc debug {level str} {
     global debug_level
@@ -723,6 +743,11 @@ define ip-proto 51 ah {mtu} {
     return $ah
 }
 
     return $ah
 }
 
+proc udp-rport {} {
+    get-for udp
+    get port enum-rand 0 0xffff
+    return $port
+}
 
 define ip-proto 17 udp {mtu} {
     # RFC768
 
 define ip-proto 17 udp {mtu} {
     # RFC768
@@ -745,15 +770,11 @@ define ip-proto 17 udp {mtu} {
     } else {
        set def_port x
     }
     } else {
        set def_port x
     }
-    if {"$style" != "servers"} {
-       get port enum-rand 0 0xffff
-       set rand_port $port
-    }
     switch -exact $style {
     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 }
+       random  { set source_port [udp-rport]; set dest_port [udp-rport] }
+       request { set source_port [udp-rport]; set dest_port $def_port   }
+       reply   { set source_port $def_port;   set dest_port [udp-rport] }
+       servers { set source_port $def_port;   set dest_port $def_port   }
     }
 
     if {"$style" != "random"} {
     }
 
     if {"$style" != "random"} {
@@ -994,14 +1015,16 @@ define ip-proto 6 tcp {mtu} {
     get urg hex 0 0xffff
 
     set options {}
     get urg hex 0 0xffff
 
     set options {}
-    get optmode choice-mult badopt 0.3 opt 0.6 noopt
+    get optmode choice-mult badopt 0.3 opt 0.3 noopt
     switch -exact $optmode {
        noopt { }
        badopt {
            get options rand 1 60 1
        }
        opt {
     switch -exact $optmode {
        noopt { }
        badopt {
            get options rand 1 60 1
        }
        opt {
-           while {[choice-prob tcp-opts-more 0.4]} {
+           set nooi 1
+           while {$nooi || [choice-prob tcp-opts-more 0.4]} {
+               set nooi 0
                get opt enum 1 255 0.5
                if {$opt == 1} {
                    assemble option {
                get opt enum 1 255 0.5
                if {$opt == 1} {
                    assemble option {