diff --git a/router/java/src/net/i2p/router/tunnel/FragmentHandler.java b/router/java/src/net/i2p/router/tunnel/FragmentHandler.java
index 962e205fc0b3d56343c2bf41cef7f9fb96d53384..892eb2e66b5d56e07af7a1e3b51fc495fc6b4c39 100644
--- a/router/java/src/net/i2p/router/tunnel/FragmentHandler.java
+++ b/router/java/src/net/i2p/router/tunnel/FragmentHandler.java
@@ -117,8 +117,9 @@ class FragmentHandler {
      * sending the resulting I2NPMessages where necessary.  The received 
      * fragments are all verified.
      *
+     * @return ok (false if corrupt)
      */
-    public void receiveTunnelMessage(byte preprocessed[], int offset, int length) {
+    public boolean receiveTunnelMessage(byte preprocessed[], int offset, int length) {
         boolean ok = verifyPreprocessed(preprocessed, offset, length);
         if (!ok) {
             if (_log.shouldLog(Log.WARN))
@@ -126,7 +127,7 @@ class FragmentHandler {
                           + preprocessed.length + " off=" +offset + " len=" + length);
             _cache.release(new ByteArray(preprocessed));
             _context.statManager().addRateData("tunnel.corruptMessage", 1);
-            return;
+            return false;
         }
         offset += HopProcessor.IV_LENGTH; // skip the IV
         offset += 4; // skip the hash segment
@@ -139,7 +140,7 @@ class FragmentHandler {
                 _context.statManager().addRateData("tunnel.corruptMessage", 1);
                 if (_log.shouldWarn())
                     _log.warn("Corrupt fragment received: off = " + offset);
-                return;
+                return false;
             }
             padding++;
         }
@@ -155,7 +156,7 @@ class FragmentHandler {
                     _context.statManager().addRateData("tunnel.corruptMessage", 1);
                     if (_log.shouldWarn())
                         _log.warn("Corrupt fragment received: off = " + off);
-                    return;
+                    return false;
                 }
                 offset = off;
             }
@@ -163,10 +164,12 @@ class FragmentHandler {
             _context.statManager().addRateData("tunnel.corruptMessage", 1);
             if (_log.shouldWarn())
                 _log.warn("Corrupt fragment received: offset = " + offset, aioobe);
+            return false;
         } catch (NullPointerException npe) {
             if (_log.shouldWarn())
                 _log.warn("Corrupt fragment received: offset = " + offset, npe);
             _context.statManager().addRateData("tunnel.corruptMessage", 1);
+            return false;
         } catch (RuntimeException e) {
             if (_log.shouldWarn())
                 _log.warn("Corrupt fragment received: offset = " + offset, e);
@@ -183,6 +186,7 @@ class FragmentHandler {
             // let's limit the damage here and skip the:
             // .transport.udp.MessageReceiver: b0rked receiving a message.. wazza huzza hmm?
             //throw e;
+            return false;
         } finally {
             // each of the FragmentedMessages populated make a copy out of the
             // payload, which they release separately, so we can release 
@@ -192,6 +196,7 @@ class FragmentHandler {
             // in order to put it in the pool, but it shouldn't cause any harm.
             _cache.release(new ByteArray(preprocessed));
         }
+        return true;
     }
     
     public int getCompleteCount() { return _completed.get(); }
diff --git a/router/java/src/net/i2p/router/tunnel/OutboundTunnelEndpoint.java b/router/java/src/net/i2p/router/tunnel/OutboundTunnelEndpoint.java
index b394f514df4e64372f21f9540a2bb7af1e4c1dbb..34bb787950f194a50c2cbdb6a7fd5dcad3a4297b 100644
--- a/router/java/src/net/i2p/router/tunnel/OutboundTunnelEndpoint.java
+++ b/router/java/src/net/i2p/router/tunnel/OutboundTunnelEndpoint.java
@@ -32,7 +32,8 @@ class OutboundTunnelEndpoint {
 
     public void dispatch(TunnelDataMessage msg, Hash recvFrom) {
         _config.incrementProcessedMessages();
-        boolean ok = _processor.process(msg.getData(), 0, msg.getData().length, recvFrom);
+        byte[] data = msg.getData();
+        boolean ok = _processor.process(data, 0, data.length, recvFrom);
         if (!ok) {
             // invalid IV
             // If we pass it on to the handler, it will fail
@@ -41,7 +42,16 @@ class OutboundTunnelEndpoint {
                 _log.warn("Invalid IV, dropping at OBEP " + _config);
             return;
         }
-        _handler.receiveTunnelMessage(msg.getData(), 0, msg.getData().length);
+        ok = _handler.receiveTunnelMessage(data, 0, data.length);
+        if (!ok) {
+            // blame previous hop
+            Hash h = _config.getReceiveFrom();
+            if (h != null) {
+                if (_log.shouldLog(Log.WARN))
+                    _log.warn(toString() + ": Blaming " + h + " 50%");
+                _context.profileManager().tunnelFailed(h, 50);
+            }
+        }
     }
     
     private class DefragmentedHandler implements FragmentHandler.DefragmentedReceiver {
diff --git a/router/java/src/net/i2p/router/tunnel/TunnelParticipant.java b/router/java/src/net/i2p/router/tunnel/TunnelParticipant.java
index c27ceecb39f56479fe7cde56cc10923ccf6aa2bc..4741927705e62b9dd0afb99bd300853c64c19453 100644
--- a/router/java/src/net/i2p/router/tunnel/TunnelParticipant.java
+++ b/router/java/src/net/i2p/router/tunnel/TunnelParticipant.java
@@ -122,10 +122,26 @@ class TunnelParticipant {
                                                   new TimeoutJob(_context, msg), MAX_LOOKUP_TIME);
             }
         } else {
-            _inboundEndpointProcessor.getConfig().incrementProcessedMessages();
-            if (_log.shouldLog(Log.DEBUG))
-                _log.debug("Receive fragment: on " + _config + ": " + msg);
-            _handler.receiveTunnelMessage(data, 0, data.length);
+            // IBEP
+            TunnelCreatorConfig cfg = _inboundEndpointProcessor.getConfig();
+            cfg.incrementProcessedMessages();
+            ok = _handler.receiveTunnelMessage(data, 0, data.length);
+            if (ok) {
+                if (_log.shouldLog(Log.DEBUG))
+                    _log.debug("Receive fragment: on " + _config + ": " + msg);
+            } else {
+                // blame everybody equally
+                int lenm1 = cfg.getLength() - 1;
+                if (lenm1 > 0) {
+                    int pct = 100 / (lenm1);
+                    for (int i = 0; i < lenm1; i++) {
+                        Hash h = cfg.getPeer(i);
+                        if (_log.shouldLog(Log.WARN))
+                            _log.warn(toString() + ": Blaming " + h + ' ' + pct + '%');
+                        _context.profileManager().tunnelFailed(h, pct);
+                    }
+                }
+            }
         }
     }