chiark / gitweb /
server/peer.c, server/tests.at: Handle NAT swapping over peer addresses.
authorMark Wooding <mdw@distorted.org.uk>
Mon, 7 May 2012 13:37:05 +0000 (14:37 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Mon, 7 May 2012 14:32:06 +0000 (15:32 +0100)
Previously, we'd notice when a mobile peer switched address (e.g., due
to NAT) to one that wasn't currently known; but it seems that some
particularly awful NAT boxes will actually swap over the addresses
assigned to two peers on the wrong side of it.  The static hub peer will
see this as a bunch of decryption failures but not do anything about
it.  Eventually the mobile peers will notice a ping timeout and
reconnect, but this can take a while.

So, when we get a decryption failure from a mobile peer, see whether any
other mobile peers are interested in it.

server/peer.c
server/tests.at

index 02fceed..308ab1d 100644 (file)
@@ -215,20 +215,21 @@ static int p_decrypt(peer **pp, addr *a, size_t n,
 
   /* --- See whether any mobile peer is interested --- */
 
-  FOREACH_PEER(pp, {
-    if (pp == q || !(pp->spec.f & PSF_MOBILE)) continue;
-    if ((err = ksl_decrypt(&pp->ks, ty, bin, bout)) == KSERR_DECRYPT) {
+  p = 0;
+  FOREACH_PEER(qq, {
+    if (qq == q || !(qq->spec.f & PSF_MOBILE)) continue;
+    if ((err = ksl_decrypt(&qq->ks, ty, bin, bout)) == KSERR_DECRYPT) {
       T( trace(T_PEER, "peer: peer `%s' failed to decrypt",
-              p_name(pp)); )
+              p_name(qq)); )
        continue;
     } else {
-      p = pp;
+      p = qq;
       IF_TRACING(T_PEER, {
        if (!err)
-         trace(T_PEER, "peer: peer `%s' reports success", p_name(pp));
+         trace(T_PEER, "peer: peer `%s' reports success", p_name(qq));
        else {
          trace(T_PEER, "peer: peer `%s' reports decryption error %d",
-               p_name(pp), err);
+               p_name(qq), err);
        }
       })
       break;
@@ -239,7 +240,13 @@ static int p_decrypt(peer **pp, addr *a, size_t n,
 
 searched:
   if (!p) {
-    a_warn("PEER", "-", "unexpected-source", "?ADDR", a, A_END);
+    if (!q)
+      a_warn("PEER", "-", "unexpected-source", "?ADDR", a, A_END);
+    else {
+      a_warn("PEER", "?PEER", p, "decrypt-failed",
+            "error-code", "%d", err, A_END);
+      p_rxupdstats(q, n);
+    }
     return (-1);
   }
 
@@ -252,6 +259,7 @@ searched:
    */
 
   if (!err) {
+    *pp = p;
     if (!q) {
       T( trace(T_PEER, "peer: updating address for `%s'", p_name(p)); )
       pa = am_find(&byaddr, a, sizeof(peer_byaddr), &f); assert(!f);
index c490ff2..ab64c53 100644 (file)
@@ -38,6 +38,8 @@ m4_define([TRIPE],
      $abs_top_builddir/server/tripe -F -d. -aadmin -p0 -b127.0.0.1 -talice])
 m4_define([TRIPECTL], [$abs_top_builddir/client/tripectl -d. -aadmin])
 m4_define([USLIP], [$abs_top_builddir/uslip/tripe-uslip])
+m4_define([PKSTREAM],
+  [$abs_top_builddir/pkstream/pkstream -b127.0.0.1 -p127.0.0.1])
 
 ## Sequences.  (These are used for testing the replay protection machinery.)
 m4_define([R32], [ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15   dnl
@@ -228,13 +230,15 @@ m4_define([AWAIT_KXDONE], [
   TRIPECTL -d$4 WARN test POP
 ])
 
-## ESTABLISH(adir, aname, aopts, bdir, bname, bopts)
+## ESTABLISH(adir, aname, aopts, bdir, bname, bopts, [aport], [bport])
 m4_define([ESTABLISH], [
 
   ## Set up the establishment.
   AWAIT_KXDONE([$1], [$2], [$4], [$5], [
-    AT_CHECK([TRIPECTL -d$1 ADD -cork $6 $5 INET 127.0.0.1 $(cat $4/port)])
-    AT_CHECK([TRIPECTL -d$4 ADD $3 $2 INET 127.0.0.1 $(cat $1/port)])
+    AT_CHECK([TRIPECTL -d$1 ADD -cork $6 $5 INET 127.0.0.1 \
+      m4_if([$8], [], [$(cat $4/port)], [$8])])
+    AT_CHECK([TRIPECTL -d$4 ADD $3 $2 INET 127.0.0.1 \
+      m4_if([$7], [], [$(cat $1/port)], [$7])])
   ])
 
   ## Check transport pinging.
@@ -355,6 +359,71 @@ WITH_2TRIPES([alice], [bob], [-nslip], [-talice], [-tbob], [
 AT_CLEANUP
 
 ###--------------------------------------------------------------------------
+### Mobile peer tracking.
+
+AT_SETUP([peer tracking])
+AT_KEYWORDS([mobile])
+export TRIPE_SLIPIF=USLIP
+
+for p in alice bob carol; do (mkdir $p; cd $p; SETUPDIR([alpha])); done
+
+## WITH_PKSTREAM(adir, aport, bdir, bport, body)
+m4_define([WITH_PKSTREAM], [
+  echo >&2 "pkstream: $1 <--> :$2 <-pkstream-> :$4 <--> $3"
+  PKSTREAM -l$4 127.0.0.1:$4 127.0.0.1:$(cat $3/port)& pkstream_$3_$1=$!
+  sleep 1
+  PKSTREAM -c127.0.0.1:$4 127.0.0.1:$2 127.0.0.1:$(cat $1/port)&
+  pkstream_$1_$3=$!
+  set +x
+  $5
+  kill $pkstream_$3_$1 $pkstream_$1_$3
+])
+
+WITH_3TRIPES([alice], [bob], [carol], [-nslip],
+            [-talice], [-tbob], [-tcarol], [
+
+  ## We need an indirection layer between the two peers so that we can
+  ## simulate the effects of NAT remapping.  The nearest thing we have to
+  ## this is pkstream, so we may as well use that.
+  ##
+  ## alice <--> :5311 <-pkstream-> :5312 <--> bob
+  ## alice <--> :5321 <-pkstream-> :5322 <--> carol
+
+  WITH_PKSTREAM([alice], [5311], [bob], [5312], [
+    ESTABLISH([alice], [alice], [], [bob], [bob], [-mobile], [5312], [5311])
+  ])
+
+  WITH_PKSTREAM([alice], [5319], [bob], [5312], [
+    COMMS_EPING([bob], [bob], [alice], [alice])
+    COMMS_SLIP([bob], [bob], [alice], [alice])
+  ])
+
+  WITH_PKSTREAM([alice], [5321], [carol], [5322], [
+    ESTABLISH([alice], [alice], [], [carol], [carol], [-mobile],
+       [5322], [5321])
+  ])
+
+  WITH_PKSTREAM([alice], [5311], [bob], [5312], [
+  WITH_PKSTREAM([alice], [5321], [carol], [5322], [
+    COMMS_EPING([bob], [bob], [alice], [alice])
+    COMMS_EPING([carol], [carol], [alice], [alice])
+    COMMS_SLIP([bob], [bob], [alice], [alice])
+    COMMS_SLIP([carol], [carol], [alice], [alice])
+  ])])
+
+  WITH_PKSTREAM([alice], [5321], [bob], [5312], [
+  WITH_PKSTREAM([alice], [5311], [carol], [5322], [
+    COMMS_EPING([bob], [bob], [alice], [alice])
+    COMMS_EPING([carol], [carol], [alice], [alice])
+    COMMS_SLIP([bob], [bob], [alice], [alice])
+    COMMS_SLIP([carol], [carol], [alice], [alice])
+  ])])
+  wait
+])
+
+AT_CLEANUP
+
+###--------------------------------------------------------------------------
 ### Services.
 
 AT_SETUP([server services])