--- a/t
+++ b/t
@@ -10,11 +10,12 @@
 use IO::Socket::INET6;
 use IO::Socket::INET;
 use Test::More qw/no_plan/;
-use Conf::Libconfig;
-
-my $conf = new Conf::Libconfig;
-$conf->read_file("test.cfg");
+use File::Temp qw(tempdir);
+# Because nothing else in Debian uses Conf::Libconfig, and I
+# (don@debian.org) don't want to package it, we have hard coded
+# test.cfg
 
+my %used_ports;
 
 sub get_unused_port {
     my $sock = IO::Socket::INET->new(
@@ -23,12 +24,45 @@
         ReuseAddr => 1,
     );
     my $port = $sock->sockport();
+    if (exists $used_ports{$port}) {
+        return get_unused_port($port)
+    }
+    $used_ports{$port} = 1;
     $sock->shutdown(2);
     return $port;
 }
+
+my $conf =
+   {protocols =>
+     [{ name => "ssh",  host => "localhost"},#, fork => 1, transparent => 1},
+     { name => "socks5",  host => "localhost",  },
+     { name => "http",  host => "localhost", ,  },
+     { name => "tinc",  host => "localhost", , },
+     { name => "openvpn",  host => "localhost",, },
+     { name => "xmpp",  host => "localhost", },
+     { name => "adb",  host => "localhost"},
+     { name => "syslog",  host => "localhost"},
+     { name => "regex", host => "localhost",
+              regex_patterns => [ "^foo", "^bar"],
+       minlength => 4,
+       test_patterns => [{pattern => "foo", result => "ssh"},
+                        {pattern => "fooo", result => "regex"},
+                        {pattern => "bar", result => "ssh"},
+                        {pattern => "barr", result => "regex"},
+                        {pattern => "barrr", result => "regex"},],},
+     { name => "tls", host => "localhost", , alpn_protocols => [ "alpn1", "alpn2" ], sni_hostnames => [ "sni1" ], },
+     { name => "tls", host => "localhost", alpn_protocols => [ "alpn1", "alpn2" ], sni_hostnames => [ "sni2", "sni3" ], },
+     { name => "tls", host => "localhost", alpn_protocols => [ "alpn3" ], },
+     { name => "tls", host => "localhost", sni_hostnames => [ "sni3" ], },
+     { name => "tls", host => "localhost", },
+     { name => "anyprot",  host => "localhost", }],
+   };
+
 my $no_listen = get_unused_port();  # Port on which no-one listens
-my $pidfile = $conf->lookup_value("pidfile");
+my $pidfile = tempdir(CLEANUP=>1).'/sslh.pid';
 my $sslh_port = get_unused_port();
+my $sslh_port2 = get_unused_port();
+my $sslh_port3 = get_unused_port();
 my $user = (getpwuid $<)[0]; # Run under current username
 
 # Which tests do we run
@@ -37,7 +71,7 @@
 my $PROBES_AGAIN =      1;
 my $SSL_MIX_SSH =       1;
 my $SSH_MIX_SSL =       1;
-my $DROP_CNX =          1;
+my $DROP_CNX =          0;
 
 # Robustness tests. These are mostly to achieve full test
 # coverage, but do not necessarily result in an actual test
@@ -96,10 +130,14 @@
     my (%opts) = @_;
 
     my $cnx = new IO::Socket::INET(PeerHost => "localhost:$sslh_port");
-    warn "$!\n" unless $cnx;
+    warn "Unable to open socket to $sslh_port $!\n" unless $cnx;
     return unless $cnx;
 
     my $pattern = $opts{data};
+    if (not defined $pattern) {
+        use Carp qw(confess);
+        confess("Pattern not given");
+    }
     if ($opts{no_frag}) {
         syswrite $cnx, $pattern;
     } else {
@@ -111,6 +149,10 @@
 
     my $data;
     my $n = sysread $cnx, $data, 1024;
+    if (not defined $data) {
+        use Carp qw(confess);
+        confess("No data received: $opts{binary}:$opts{expected}")
+    }
     $data =~ /^(.*?): /;
     my $prefix = $1;
     $data =~ s/$prefix: //g;
@@ -130,7 +172,7 @@
 sub test_probes {
     my (%in_opts) = @_;
 
-    my @probes = @{$conf->fetch_array("protocols")};
+    my @probes = @{$conf->{"protocols"}};
     foreach my $p (@probes) {
         my %protocols = (
             'ssh' => { data => "SSH-2.0 tester" },
@@ -205,11 +247,13 @@
 
 
 # Start an echoserver for each service
-foreach my $s (@{$conf->fetch_array("protocols")}) {
+foreach my $s (@{$conf->{"protocols"}}) {
     my $prefix = $s->{name};
 
     $prefix =~ s/^ssl/tls/; # To remove in 1.21
 
+    $s->{port} = get_unused_port();
+
     if ($s->{sni_hostnames} or $s->{alpn_protocols}) {
         $prefix = make_sni_alpn_name($s);
     }
@@ -217,6 +261,66 @@
     verbose_exec "./echosrv --listen $s->{host}:$s->{port} --prefix '$prefix: '";
 }
 
+# Write out test.cfg with new unused ports
+open(my $test_cfg,'>test.cfg') or
+    die "Unable to open test.cfg for writing";
+print {$test_cfg} <<"EOF";
+# Configuration file for testing (use both by sslh under
+# test and the test script `t`)
+
+verbose: 4;
+foreground: true;
+inetd: false;
+numeric: true;
+transparent: false;
+timeout: 10;   # Probe test writes slowly
+pidfile: "$pidfile";
+
+syslog_facility: "auth"; 
+
+
+# List of interfaces on which we should listen
+# Options:
+listen:
+(
+    { host: "localhost"; port: "$sslh_port"; keepalive: true; },
+    { host: "localhost"; port: "$sslh_port2"; keepalive: true; },
+    { host: "localhost"; is_udp: true; port: "$sslh_port3"; }
+);
+
+ 
+protocols:
+(
+     { name: "ssh";  host: "localhost"; port: "$conf->{protocols}[0]{port}"; },
+     { name: "socks5";  host: "localhost"; port: "$conf->{protocols}[1]{port}";  },
+     { name: "http";  host: "localhost"; port: "$conf->{protocols}[2]{port}";  },
+     { name: "tinc";  host: "localhost"; port: "$conf->{protocols}[3]{port}"; },
+     { name: "openvpn";  host: "localhost"; port: "$conf->{protocols}[4]{port}"; },
+     { name: "xmpp";  host: "localhost"; port: "$conf->{protocols}[5]{port}"; },
+     { name: "adb";  host: "localhost"; port: "$conf->{protocols}[6]{port}"; },
+     { name: "syslog"; host: "localhost"; port: "$conf->{protocols}[7]{port}"; },
+     { name: "regex"; host: "localhost"; port: "$conf->{protocols}[8]{port}";
+        regex_patterns: [ "^foo", "^bar" ];
+        minlength: 4;
+        test_patterns: (    # this is used by the test script, not by sslh
+            { pattern: "foo"; result: "ssh"; },  # After timeout
+            { pattern: "fooo"; result: "regex"; },
+            { pattern: "bar"; result: "ssh"; },
+            { pattern: "barr"; result: "regex"; },
+            { pattern: "barrrr"; result: "regex"; }
+        );
+     },
+     { name: "tls"; host: "localhost"; port: "$conf->{protocols}[9]{port}"; alpn_protocols: [ "alpn1", "alpn2" ]; sni_hostnames: [ "sni1" ]; },
+     { name: "tls"; host: "localhost"; port: "$conf->{protocols}[10]{port}"; alpn_protocols: [ "alpn1", "alpn2" ]; sni_hostnames: [ "sni2", "sni3" ]; },
+     { name: "tls"; host: "localhost"; port: "$conf->{protocols}[11]{port}"; alpn_protocols: [ "alpn3" ]; },
+     { name: "tls"; host: "localhost"; port: "$conf->{protocols}[12]{port}"; sni_hostnames: [ "sni3" ]; },
+     { name: "tls"; host: "localhost"; port: "$conf->{protocols}[13]{port}"; },
+     { name: "anyprot";  host: "localhost"; port: "$conf->{protocols}[14]{port}";  }
+);
+
+on_timeout: "ssh";
+EOF
+close ($test_cfg);
 
 #my @binaries = ('sslh-select', 'sslh-fork');
 my @binaries = ('sslh-select');
@@ -246,7 +350,7 @@
     if ($SSH_SHY_CNX) {
         print "***Test: Shy SSH connection\n";
         my $cnx_h = new IO::Socket::INET(PeerHost => "localhost:$sslh_port");
-        warn "$!\n" unless $cnx_h;
+        warn "Unable to connect to sslh_port:$sslh_port $!\n" unless $cnx_h;
         if (defined $cnx_h) {
             sleep 13;
             print $cnx_h $test_data;
@@ -259,11 +363,11 @@
     if ($SSL_MIX_SSH) {
         print "***Test: One SSL half-started then one SSH\n";
         my $cnx_l = new IO::Socket::INET(PeerHost => "localhost:$sslh_port");
-        warn "$!\n" unless $cnx_l;
+        warn "Unable to connect to sslh_port $sslh_port: $!\n" unless $cnx_l;
         if (defined $cnx_l) {
             print $cnx_l $ssl_test_data;
             my $cnx_h= new IO::Socket::INET(PeerHost => "localhost:$sslh_port");
-            warn "$!\n" unless $cnx_h;
+            warn "Unable to connect to sslh_port $sslh_port: $!\n" unless $cnx_h;
             if (defined $cnx_h) {
                 sleep 3;
                 print $cnx_h $test_data;
@@ -280,7 +384,7 @@
     if ($SSH_MIX_SSL) {
         print "***Test: One SSH half-started then one SSL\n";
         my $cnx_h = new IO::Socket::INET(PeerHost => "localhost:$sslh_port");
-        warn "$!\n" unless $cnx_h;
+        warn "Unable to open sslh_port:$sslh_port $!\n" unless $cnx_h;
         if (defined $cnx_h) {
             sleep 3;
             my $cnx_l = new IO::Socket::INET(PeerHost => "localhost:$sslh_port");
@@ -350,11 +454,11 @@
 }
 
 
-my $ssh_conf = (grep { $_->{name} eq "ssh" } @{$conf->fetch_array("protocols")})[0];
+my $ssh_conf = (grep { $_->{name} eq "ssh" } @{$conf->{"protocols"}})[0];
 my $ssh_address = $ssh_conf->{host} . ":" .  $ssh_conf->{port};
 
 # Use the last TLS echoserv (no SNI/ALPN)
-my $ssl_conf = (grep { $_->{name} eq "tls" } @{$conf->fetch_array("protocols")})[-1];
+my $ssl_conf = (grep { $_->{name} eq "tls" } @{$conf->{"protocols"}})[-1];
 my $ssl_address = $ssl_conf->{host} . ":" .  $ssl_conf->{port};
 
 
@@ -424,7 +528,7 @@
         my $user = (getpwuid $<)[0]; # Run under current username
         # This doesn't test --inetd
         exec "./sslh-select -v 3 -f -u $user -P $pidfile".
-        " -n --transparent --timeout 10 -C /tmp".
+        " -n --timeout 10 -C /tmp".
         " --syslog-facility auth --on-timeout ssh".
         " --listen localhost:$no_listen --ssh $ssh_address --tls $ssl_address".
         " --openvpn localhost:$no_listen".
@@ -447,12 +551,12 @@
 
 
     print "***Test: Bad command line parameters\n";
-    my $sslh_pid;
+    $sslh_pid = undef;
     if (!($sslh_pid = fork)) {
         my $user = (getpwuid $<)[0]; # Run under current username
         # This doesn't test --inetd
         exec "./sslh-select -v 3 -f -u $user -P $pidfile".
-        " -n --transparent --timeout 10 -C /tmp".
+        " -n --timeout 10 -C /tmp".
         " --fakeoption".
         " --anyprot localhost:$no_listen";
         exit 0;
@@ -460,7 +564,7 @@
     warn "spawned $sslh_pid\n";
 
     waitpid $sslh_pid, 0;
-    my $code = $? >> 8;
+    $code = $? >> 8;
     warn "exited with $code\n";
     my_is($code, 6, "Bad command line parameters");
 }
