* Transports:

- Prefer IPv6 by default
   - Fix IPv6-only option
   - Don't try NTCP IPv6 addresses unless we have one
   - Fix non-%16 SSU padding in data and session confirmed packets; enable by default
   - Log tweaks
This commit is contained in:
zzz
2013-07-25 18:52:45 +00:00
parent ffda7f6326
commit 19faa352e3
7 changed files with 81 additions and 20 deletions

View File

@@ -1,3 +1,13 @@
2012-07-25 zzz
* Transports:
- Prefer IPv6 by default
- Fix IPv6-only option
- Don't try NTCP IPv6 addresses unless we have one
- Fix non-%16 SSU padding; enable by default
* Tunnels:
- Make expl. default 3 hops (ticket #966)
- Allow expl. fallback up to -2 hops
2012-07-24 zzz
* GeoIP: Fix lookups, broken in IPv6 branch
* UPnP:

View File

@@ -18,7 +18,7 @@ public class RouterVersion {
/** deprecated */
public final static String ID = "Monotone";
public final static String VERSION = CoreVersion.VERSION;
public final static long BUILD = 10;
public final static long BUILD = 11;
/** for example "-test" */
public final static String EXTRA = "";

View File

@@ -243,8 +243,8 @@ public abstract class TransportImpl implements Transport {
if (!sendSuccessful)
msg.transportFailed(getStyle());
if (msToSend > 1000) {
if (_log.shouldLog(Log.WARN))
if (msToSend > 1500) {
if (_log.shouldLog(Log.INFO))
_log.warn(getStyle() + " afterSend slow: " + (sendSuccessful ? "success " : "FAIL ")
+ msg.getMessageSize() + " byte "
+ msg.getMessageType() + ' ' + msg.getMessageId() + " to "
@@ -577,14 +577,24 @@ public abstract class TransportImpl implements Transport {
*/
protected List<RouterAddress> getTargetAddresses(RouterInfo target) {
List<RouterAddress> rv = target.getTargetAddresses(getStyle());
if (rv.isEmpty())
return rv;
// Shuffle so everybody doesn't use the first one
if (rv.size() > 1) {
if (rv.size() > 1)
Collections.shuffle(rv, _context.random());
TransportUtil.IPv6Config config = getIPv6Config();
int adj;
switch (config) {
TransportUtil.IPv6Config config = getIPv6Config();
int adj;
switch (config) {
case IPV6_DISABLED:
adj = 10; break;
adj = 10;
/**** IPv6 addresses will be rejected in isPubliclyRoutable()
for (Iterator<RouterAddress> iter = rv.iterator(); iter.hasNext(); ) {
byte[] ip = iter.next().getIP();
if (ip != null && ip.length == 16)
iter.remove();
}
****/
break;
case IPV6_NOT_PREFERRED:
adj = 1; break;
default:
@@ -593,10 +603,17 @@ public abstract class TransportImpl implements Transport {
case IPV6_PREFERRED:
adj = -1; break;
case IPV6_ONLY:
adj = -10; break;
}
Collections.sort(rv, new AddrComparator(adj));
adj = -10;
// IPv4 addresses not rejected in isPubliclyRoutable()
for (Iterator<RouterAddress> iter = rv.iterator(); iter.hasNext(); ) {
byte[] ip = iter.next().getIP();
if (ip != null && ip.length == 4)
iter.remove();
}
break;
}
if (rv.size() > 1)
Collections.sort(rv, new AddrComparator(adj));
return rv;
}

View File

@@ -52,7 +52,7 @@ public abstract class TransportUtil {
}
private static final Map<String, IPv6Config> BY_NAME = new HashMap<String, IPv6Config>();
public static final IPv6Config DEFAULT_IPV6_CONFIG = IPv6Config.IPV6_DISABLED;
public static final IPv6Config DEFAULT_IPV6_CONFIG = IPv6Config.IPV6_PREFERRED;
static {
for (IPv6Config cfg : IPv6Config.values()) {
@@ -60,6 +60,7 @@ public abstract class TransportUtil {
}
// alias
BY_NAME.put("true", IPv6Config.IPV6_ENABLED);
BY_NAME.put("disable", IPv6Config.IPV6_DISABLED);
}
public static IPv6Config getIPv6Config(RouterContext ctx, String transportStyle) {

View File

@@ -25,6 +25,7 @@ import net.i2p.data.RouterIdentity;
import net.i2p.router.CommSystemFacade;
import net.i2p.router.RouterContext;
import net.i2p.router.transport.FIFOBandwidthLimiter;
import net.i2p.util.Addresses;
import net.i2p.util.ConcurrentHashSet;
import net.i2p.util.I2PThread;
import net.i2p.util.Log;
@@ -781,8 +782,8 @@ class EventPumper implements Runnable {
SelectionKey key = con.getChannel().register(_selector, SelectionKey.OP_CONNECT);
key.attach(con);
con.setKey(key);
RouterAddress naddr = con.getRemoteAddress();
try {
RouterAddress naddr = con.getRemoteAddress();
if (naddr.getPort() <= 0)
throw new IOException("Invalid NTCP address: " + naddr);
InetSocketAddress saddr = new InetSocketAddress(naddr.getHost(), naddr.getPort());
@@ -794,7 +795,8 @@ class EventPumper implements Runnable {
processConnect(key);
}
} catch (IOException ioe) {
if (_log.shouldLog(Log.WARN)) _log.warn("error connecting", ioe);
if (_log.shouldLog(Log.WARN))
_log.warn("error connecting to " + Addresses.toString(naddr.getIP(), naddr.getPort()), ioe);
_context.statManager().addRateData("ntcp.connectFailedIOE", 1);
_transport.markUnreachable(con.getRemotePeer().calculateHash());
//if (ntcpOnly(con)) {

View File

@@ -72,6 +72,12 @@ public class NTCPTransport extends TransportImpl {
*/
private final Set<NTCPConnection> _establishing;
/**
* Do we have a public IPv6 address?
* TODO periodically update via CSFI.NetMonitor?
*/
private boolean _haveIPv6Address;
public final static String PROP_I2NP_NTCP_HOSTNAME = "i2np.ntcp.hostname";
public final static String PROP_I2NP_NTCP_PORT = "i2np.ntcp.port";
public final static String PROP_I2NP_NTCP_AUTO_PORT = "i2np.ntcp.autoport";
@@ -364,7 +370,7 @@ public class NTCPTransport extends TransportImpl {
// _log.debug("no bid when trying to send to " + peer + " as they don't have a valid ntcp address");
continue;
}
if (!isPubliclyRoutable(ip)) {
if (!isValid(ip)) {
if (! _context.getBooleanProperty("i2np.ntcp.allowLocal")) {
//_context.statManager().addRateData("ntcp.bidRejectedLocalAddress", 1);
//if (_log.shouldLog(Log.DEBUG))
@@ -376,6 +382,21 @@ public class NTCPTransport extends TransportImpl {
}
return null;
}
/**
* An IPv6 address is only valid if we are configured to support IPv6
* AND we have a public IPv6 address.
*
* @param addr may be null, returns false
* @since 0.9.8
*/
private boolean isValid(byte addr[]) {
if (addr == null) return false;
if (isPubliclyRoutable(addr) &&
(addr.length != 16 || _haveIPv6Address))
return true;
return false;
}
public boolean allowConnection() {
return countActivePeers() < getMaxConnections();
@@ -809,7 +830,12 @@ public class NTCPTransport extends TransportImpl {
public void externalAddressReceived(AddressSource source, byte[] ip, int port) {
if (_log.shouldLog(Log.WARN))
_log.warn("Received address: " + Addresses.toString(ip, port) + " from: " + source);
if (ip != null && !isPubliclyRoutable(ip)) {
if ((source == SOURCE_INTERFACE || source == SOURCE_SSU)
&& ip != null && ip.length == 16) {
// must be set before isValid() call
_haveIPv6Address = true;
}
if (ip != null && !isValid(ip)) {
if (_log.shouldLog(Log.WARN))
_log.warn("Invalid address: " + Addresses.toString(ip, port) + " from: " + source);
return;

View File

@@ -161,6 +161,7 @@ class PacketBuilder {
private static final int MAX_RESEND_ACKS_SMALL = 4;
private static final String PROP_PADDING = "i2np.udp.padding";
private static final boolean DEFAULT_ENABLE_PADDING = true;
/**
* @param transport may be null for unit testing only
@@ -408,7 +409,7 @@ class PacketBuilder {
// pad up so we're on the encryption boundary
off = pad1(data, off);
off = pad2(data, off, currentMTU);
off = pad2(data, off, currentMTU - (ipHeaderSize + UDP_HEADER_SIZE));
pkt.setLength(off);
authenticate(packet, peer.getCurrentCipherKey(), peer.getCurrentMACKey());
@@ -782,6 +783,9 @@ class PacketBuilder {
_context.random().nextBytes(data, off, paddingRequired);
off += paddingRequired;
}
// We cannot have non-mod16 (pad2) padding here, since the signature
// is at the end. As of 0.9.7 we won't decrypt past the end of the packet
// so trailing non-mod-16 data is ignored. That truncates the sig.
// BUG: NPE here if null signature
System.arraycopy(state.getSentSignature().getData(), 0, data, off, Signature.SIGNATURE_BYTES);
@@ -792,8 +796,9 @@ class PacketBuilder {
// nothing more to add beyond the identity fragment
// pad up so we're on the encryption boundary
off = pad1(data, off);
// allowed but untested
//off = pad2(data, off);
}
off = pad2(data, off);
pkt.setLength(off);
authenticate(packet, state.getCipherKey(), state.getMACKey());
setTo(packet, to, state.getSentPort());
@@ -1351,7 +1356,7 @@ class PacketBuilder {
* @since 0.9.7
*/
private int pad2(byte[] data, int off) {
if (!_context.getBooleanProperty(PROP_PADDING))
if (!_context.getProperty(PROP_PADDING, DEFAULT_ENABLE_PADDING))
return off;
int padSize = _context.random().nextInt(MAX_PAD2);
if (padSize == 0)
@@ -1370,7 +1375,7 @@ class PacketBuilder {
* @since 0.9.7
*/
private int pad2(byte[] data, int off, int maxLen) {
if (!_context.getBooleanProperty(PROP_PADDING))
if (!_context.getProperty(PROP_PADDING, DEFAULT_ENABLE_PADDING))
return off;
if (off >= maxLen)
return off;