forked from I2P_Developers/i2p.i2p
SSU2: More MTU checks
Add code for bob rejecting alice peer test address Don't allow MTU to exceed his MTU Don't use a token about to expire Send token with termination message Add internal type to termination message log tweaks
This commit is contained in:
@@ -415,6 +415,17 @@ class EstablishmentManager {
|
||||
version = 1;
|
||||
}
|
||||
}
|
||||
if (version == 2) {
|
||||
int mtu = addr.getMTU();
|
||||
if (mtu > 0 && mtu < PeerState2.MIN_MTU) {
|
||||
if (ra.getTransportStyle().equals("SSU2")) {
|
||||
_transport.markUnreachable(toHash);
|
||||
_transport.failed(msg, "MTU too small");
|
||||
return;
|
||||
}
|
||||
version = 1;
|
||||
}
|
||||
}
|
||||
if (version == 1) {
|
||||
keyBytes = addr.getIntroKey();
|
||||
} else {
|
||||
@@ -2435,6 +2446,8 @@ class EstablishmentManager {
|
||||
* @since 0.9.54
|
||||
*/
|
||||
public void addOutboundToken(RemoteHostId peer, long token, long expires) {
|
||||
// so we don't use a token about to expire
|
||||
expires -= 2*60*1000;
|
||||
if (expires < _context.clock().now())
|
||||
return;
|
||||
Token tok = new Token(token, expires);
|
||||
|
||||
@@ -202,8 +202,8 @@ class InboundEstablishState2 extends InboundEstablishState implements SSU2Payloa
|
||||
}
|
||||
|
||||
public void gotRI(RouterInfo ri, boolean isHandshake, boolean flood) throws DataFormatException {
|
||||
if (_log.shouldDebug())
|
||||
_log.debug("Got RI block: " + ri);
|
||||
//if (_log.shouldDebug())
|
||||
// _log.debug("Got RI block: " + ri);
|
||||
if (isHandshake)
|
||||
throw new DataFormatException("RI in Sess Req");
|
||||
if (_receivedUnconfirmedIdentity != null)
|
||||
@@ -275,7 +275,9 @@ class InboundEstablishState2 extends InboundEstablishState implements SSU2Payloa
|
||||
mtu = PeerState2.DEFAULT_SSU_IPV4_MTU;
|
||||
}
|
||||
} else {
|
||||
// TODO if too small, give up now
|
||||
// if too small, give up now
|
||||
if (mtu < PeerState2.MIN_MTU)
|
||||
throw new DataFormatException("MTU too small " + mtu);
|
||||
if (ra.getTransportStyle().equals(UDPTransport.STYLE2)) {
|
||||
mtu = Math.min(Math.max(mtu, PeerState2.MIN_MTU), PeerState2.MAX_MTU);
|
||||
} else {
|
||||
@@ -369,6 +371,8 @@ class InboundEstablishState2 extends InboundEstablishState implements SSU2Payloa
|
||||
}
|
||||
|
||||
public void gotToken(long token, long expires) {
|
||||
if (_log.shouldDebug())
|
||||
_log.debug("Got token: " + token + " expires " + DataHelper.formatTime(expires) + " on " + this);
|
||||
if (_receivedConfirmedIdentity == null)
|
||||
throw new IllegalStateException("RI must be first");
|
||||
_transport.getEstablisher().addOutboundToken(_remoteHostId, token, expires);
|
||||
|
||||
@@ -1059,7 +1059,8 @@ class IntroductionManager {
|
||||
}
|
||||
UDPPacket packet = _builder2.buildRelayResponse(data, bob);
|
||||
if (_log.shouldInfo())
|
||||
_log.info("Send relay response " + rcode + " as charlie " + " nonce " + nonce + " to bob " + bob);
|
||||
_log.info("Send relay response " + rcode + " as charlie " + " nonce " + nonce + " to bob " + bob +
|
||||
" for alice " + Addresses.toString(testIP, testPort) + ' ' + aliceRI);
|
||||
_transport.send(packet);
|
||||
if (rcode == SSU2Util.RELAY_ACCEPT) {
|
||||
// send hole punch with the same data we sent to Bob
|
||||
|
||||
@@ -155,9 +155,11 @@ class OutboundEstablishState2 extends OutboundEstablishState implements SSU2Payl
|
||||
mtu = PeerState2.DEFAULT_SSU_IPV4_MTU;
|
||||
}
|
||||
} else {
|
||||
// TODO if too small, give up now
|
||||
// If too small, give up now
|
||||
if (mtu < PeerState2.MIN_MTU)
|
||||
throw new IllegalArgumentException("MTU " + mtu + " too small for " + remotePeer.getHash());
|
||||
if (ra.getTransportStyle().equals(UDPTransport.STYLE2)) {
|
||||
mtu = Math.min(Math.max(mtu, PeerState2.MIN_MTU), PeerState2.MAX_MTU);
|
||||
mtu = Math.min(mtu, PeerState2.MAX_MTU);
|
||||
} else {
|
||||
if (_bobIP != null && _bobIP.length == 16)
|
||||
mtu = Math.min(Math.max(mtu, PeerState2.MIN_SSU_IPV6_MTU), PeerState2.MAX_SSU_IPV6_MTU);
|
||||
@@ -321,6 +323,8 @@ class OutboundEstablishState2 extends OutboundEstablishState implements SSU2Payl
|
||||
}
|
||||
|
||||
public void gotToken(long token, long expires) {
|
||||
if (_log.shouldDebug())
|
||||
_log.debug("Got token: " + token + " expires " + DataHelper.formatTime(expires) + " on " + this);
|
||||
_transport.getEstablisher().addOutboundToken(_remoteHostId, token, expires);
|
||||
}
|
||||
|
||||
|
||||
@@ -60,6 +60,7 @@ class PacketBuilder2 {
|
||||
static final int TYPE_CONF = 71;
|
||||
static final int TYPE_SREQ = 72;
|
||||
static final int TYPE_CREAT = 73;
|
||||
static final int TYPE_DESTROY = 74;
|
||||
|
||||
/** IPv4 only */
|
||||
public static final int IP_HEADER_SIZE = PacketBuilder.IP_HEADER_SIZE;
|
||||
@@ -100,6 +101,7 @@ class PacketBuilder2 {
|
||||
/**
|
||||
* Will a packet to 'peer' that already has 'numFragments' fragments
|
||||
* totalling 'curDataSize' bytes fit another fragment?
|
||||
* This includes the 3 byte block overhead, but NOT the 5 byte followon fragment overhead.
|
||||
*
|
||||
* This doesn't leave anything for acks or anything else.
|
||||
*
|
||||
@@ -279,7 +281,7 @@ class PacketBuilder2 {
|
||||
if (_log.shouldWarn()) {
|
||||
int maxMTU = PeerState2.MAX_MTU;
|
||||
off += MAC_LEN;
|
||||
if (off + ipHeaderSize > maxMTU) {
|
||||
if (off + ipHeaderSize > currentMTU) {
|
||||
_log.warn("Size is " + off + " for " + packet +
|
||||
" data size " + dataSize +
|
||||
" pkt size " + (off + ipHeaderSize) +
|
||||
@@ -340,11 +342,24 @@ class PacketBuilder2 {
|
||||
|
||||
/**
|
||||
* Build a data packet with a termination block.
|
||||
* This will also include acks and padding.
|
||||
* This will also include acks, a new token block, and padding.
|
||||
*/
|
||||
public UDPPacket buildSessionDestroyPacket(int reason, PeerState2 peer) {
|
||||
if (_log.shouldWarn())
|
||||
_log.warn("Sending termination " + reason + " to : " + peer);
|
||||
List<Block> blocks = new ArrayList<Block>(2);
|
||||
if (peer.getKeyEstablishedTime() - _context.clock().now() > EstablishmentManager.IB_TOKEN_EXPIRATION / 2 &&
|
||||
!_context.router().gracefulShutdownInProgress()) {
|
||||
// update token
|
||||
EstablishmentManager.Token token = _transport.getEstablisher().getInboundToken(peer.getRemoteHostId());
|
||||
Block block = new SSU2Payload.NewTokenBlock(token.token, token.expires);
|
||||
blocks.add(block);
|
||||
}
|
||||
Block block = new SSU2Payload.TerminationBlock(reason, peer.getReceivedMessages().getHighestSet());
|
||||
return buildPacket(Collections.emptyList(), Collections.singletonList(block), peer);
|
||||
blocks.add(block);
|
||||
UDPPacket packet = buildPacket(Collections.emptyList(), blocks, peer);
|
||||
packet.setMessageType(TYPE_DESTROY);
|
||||
return packet;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1267,7 +1267,8 @@ public class PeerState {
|
||||
synchronized void setHisMTU(int mtu) {
|
||||
if (mtu <= _minMTU || mtu >= _largeMTU)
|
||||
return;
|
||||
_largeMTU = mtu;
|
||||
if (mtu < _largeMTU)
|
||||
_largeMTU = mtu;
|
||||
if (mtu < _mtu)
|
||||
_mtu = mtu;
|
||||
}
|
||||
|
||||
@@ -563,14 +563,16 @@ public class PeerState2 extends PeerState implements SSU2Payload.PayloadCallback
|
||||
public void gotACK(long ackThru, int acks, byte[] ranges) {
|
||||
int hc = (((int) ackThru) << 8) ^ (acks << 24) ^ DataHelper.hashCode(ranges);
|
||||
if (_lastAckHashCode.getAndSet(hc) == hc) {
|
||||
if (_log.shouldDebug())
|
||||
_log.debug("Got dup ACK block: " + SSU2Bitfield.toString(ackThru, acks, ranges, (ranges != null ? ranges.length / 2 : 0)));
|
||||
//if (_log.shouldDebug())
|
||||
// _log.debug("Got dup ACK block: " + SSU2Bitfield.toString(ackThru, acks, ranges, (ranges != null ? ranges.length / 2 : 0)));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
SSU2Bitfield ackbf = SSU2Bitfield.fromACKBlock(ackThru, acks, ranges, (ranges != null ? ranges.length / 2 : 0));
|
||||
if (_log.shouldDebug())
|
||||
_log.debug("Got new ACK block: " + SSU2Bitfield.toString(ackThru, acks, ranges, (ranges != null ? ranges.length / 2 : 0)));
|
||||
_log.debug("Got new ACK block from " +
|
||||
_remotePeer.toBase64().substring(0,6) + ' ' +
|
||||
SSU2Bitfield.toString(ackThru, acks, ranges, (ranges != null ? ranges.length / 2 : 0)));
|
||||
// calls bitSet() below
|
||||
ackbf.forEachAndNot(_ackedMessages, this);
|
||||
} catch (Exception e) {
|
||||
@@ -583,8 +585,8 @@ public class PeerState2 extends PeerState implements SSU2Payload.PayloadCallback
|
||||
}
|
||||
|
||||
public void gotTermination(int reason, long count) {
|
||||
if (_log.shouldDebug())
|
||||
_log.debug("Got TERMINATION block, reason: " + reason + " count: " + count + " on " + this);
|
||||
if (_log.shouldInfo())
|
||||
_log.info("Got TERMINATION block, reason: " + reason + " count: " + count + " on " + this);
|
||||
_transport.getEstablisher().receiveSessionDestroy(_remoteHostId, this);
|
||||
}
|
||||
|
||||
|
||||
@@ -125,6 +125,7 @@ final class SSU2Util {
|
||||
public static final int TEST_REJECT_BOB_NO_CHARLIE = 2;
|
||||
public static final int TEST_REJECT_BOB_LIMIT = 3;
|
||||
public static final int TEST_REJECT_BOB_SIGFAIL = 4;
|
||||
public static final int TEST_REJECT_BOB_ADDRESS = 5;
|
||||
public static final int TEST_REJECT_CHARLIE_UNSPEC = 64;
|
||||
public static final int TEST_REJECT_CHARLIE_ADDRESS = 65;
|
||||
public static final int TEST_REJECT_CHARLIE_LIMIT = 66;
|
||||
|
||||
Reference in New Issue
Block a user