forked from I2P_Developers/i2p.i2p
Transport: Save IPv6 firewalled state across restarts (ticket #2175)
Use EnumSets in UDPTransport
This commit is contained in:
@ -68,6 +68,9 @@ public abstract class TransportImpl implements Transport {
|
|||||||
private static final long UNREACHABLE_PERIOD = 5*60*1000;
|
private static final long UNREACHABLE_PERIOD = 5*60*1000;
|
||||||
private static final long WAS_UNREACHABLE_PERIOD = 30*60*1000;
|
private static final long WAS_UNREACHABLE_PERIOD = 30*60*1000;
|
||||||
|
|
||||||
|
/** @since 0.9.44 */
|
||||||
|
protected static final String PROP_IPV6_FIREWALLED = "i2np.lastIPv6Firewalled";
|
||||||
|
|
||||||
static {
|
static {
|
||||||
long maxMemory = SystemVersion.getMaxMemory();
|
long maxMemory = SystemVersion.getMaxMemory();
|
||||||
long min = 512;
|
long min = 512;
|
||||||
|
@ -872,9 +872,12 @@ public class NTCPTransport extends TransportImpl {
|
|||||||
props.setProperty(RouterAddress.PROP_HOST, ia.getHostAddress());
|
props.setProperty(RouterAddress.PROP_HOST, ia.getHostAddress());
|
||||||
props.setProperty(RouterAddress.PROP_PORT, Integer.toString(port));
|
props.setProperty(RouterAddress.PROP_PORT, Integer.toString(port));
|
||||||
addNTCP2Options(props);
|
addNTCP2Options(props);
|
||||||
int cost = getDefaultCost(ia instanceof Inet6Address);
|
boolean ipv6 = ia instanceof Inet6Address;
|
||||||
myAddress = new RouterAddress(getPublishStyle(), props, cost);
|
if (!ipv6 || !_context.getBooleanProperty(PROP_IPV6_FIREWALLED)) {
|
||||||
replaceAddress(myAddress);
|
int cost = getDefaultCost(ipv6);
|
||||||
|
myAddress = new RouterAddress(getPublishStyle(), props, cost);
|
||||||
|
replaceAddress(myAddress);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (_enableNTCP2) {
|
} else if (_enableNTCP2) {
|
||||||
setOutboundNTCP2Address();
|
setOutboundNTCP2Address();
|
||||||
|
@ -9,6 +9,7 @@ import java.net.UnknownHostException;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.EnumSet;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@ -169,7 +170,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
|||||||
public static final String PROP_IP_CHANGE = "i2np.lastIPChange";
|
public static final String PROP_IP_CHANGE = "i2np.lastIPChange";
|
||||||
public static final String PROP_LAPTOP_MODE = "i2np.laptopMode";
|
public static final String PROP_LAPTOP_MODE = "i2np.laptopMode";
|
||||||
/** @since 0.9.43 */
|
/** @since 0.9.43 */
|
||||||
public static final String PROP_IPV6= "i2np.lastIPv6";
|
public static final String PROP_IPV6 = "i2np.lastIPv6";
|
||||||
|
|
||||||
/** do we require introducers, regardless of our status? */
|
/** do we require introducers, regardless of our status? */
|
||||||
public static final String PROP_FORCE_INTRODUCERS = "i2np.udp.forceIntroducers";
|
public static final String PROP_FORCE_INTRODUCERS = "i2np.udp.forceIntroducers";
|
||||||
@ -235,6 +236,42 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
|||||||
*/
|
*/
|
||||||
private static final String MIN_V6_PEER_TEST_VERSION = "0.9.27";
|
private static final String MIN_V6_PEER_TEST_VERSION = "0.9.27";
|
||||||
|
|
||||||
|
// various state bitmaps
|
||||||
|
|
||||||
|
private static final Set<Status> STATUS_IPV4_FW = EnumSet.of(Status.DIFFERENT,
|
||||||
|
Status.REJECT_UNSOLICITED,
|
||||||
|
Status.IPV4_FIREWALLED_IPV6_OK,
|
||||||
|
Status.IPV4_SNAT_IPV6_OK,
|
||||||
|
Status.IPV4_OK_IPV6_FIREWALLED);
|
||||||
|
|
||||||
|
private static final Set<Status> STATUS_IPV6_FW = EnumSet.of(Status.IPV4_OK_IPV6_FIREWALLED,
|
||||||
|
Status.IPV4_UNKNOWN_IPV6_FIREWALLED,
|
||||||
|
Status.IPV4_DISABLED_IPV6_FIREWALLED);
|
||||||
|
|
||||||
|
private static final Set<Status> STATUS_IPV6_FW_2 = EnumSet.of(Status.IPV4_OK_IPV6_FIREWALLED,
|
||||||
|
Status.IPV4_UNKNOWN_IPV6_FIREWALLED,
|
||||||
|
Status.IPV4_DISABLED_IPV6_FIREWALLED,
|
||||||
|
Status.DIFFERENT,
|
||||||
|
Status.REJECT_UNSOLICITED);
|
||||||
|
|
||||||
|
private static final Set<Status> STATUS_IPV6_OK = EnumSet.of(Status.OK,
|
||||||
|
Status.IPV4_UNKNOWN_IPV6_OK,
|
||||||
|
Status.IPV4_FIREWALLED_IPV6_OK,
|
||||||
|
Status.IPV4_DISABLED_IPV6_OK,
|
||||||
|
Status.IPV4_SNAT_IPV6_OK);
|
||||||
|
|
||||||
|
private static final Set<Status> STATUS_NO_RETEST = EnumSet.of(Status.OK,
|
||||||
|
Status.IPV4_OK_IPV6_UNKNOWN,
|
||||||
|
Status.IPV4_OK_IPV6_FIREWALLED,
|
||||||
|
Status.IPV4_DISABLED_IPV6_OK,
|
||||||
|
Status.IPV4_DISABLED_IPV6_UNKNOWN,
|
||||||
|
Status.IPV4_DISABLED_IPV6_FIREWALLED,
|
||||||
|
Status.DISCONNECTED);
|
||||||
|
|
||||||
|
private static final Set<Status> STATUS_NEED_INTRO = EnumSet.of(Status.REJECT_UNSOLICITED,
|
||||||
|
Status.IPV4_FIREWALLED_IPV6_OK,
|
||||||
|
Status.IPV4_FIREWALLED_IPV6_UNKNOWN);
|
||||||
|
|
||||||
|
|
||||||
public UDPTransport(RouterContext ctx, DHSessionKeyBuilder.Factory dh) {
|
public UDPTransport(RouterContext ctx, DHSessionKeyBuilder.Factory dh) {
|
||||||
super(ctx);
|
super(ctx);
|
||||||
@ -555,17 +592,18 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
|||||||
if (hasv6)
|
if (hasv6)
|
||||||
continue;
|
continue;
|
||||||
hasv6 = true;
|
hasv6 = true;
|
||||||
// FIXME we need to check and time out after an hour of no inbound ipv6,
|
if (isIPv6Firewalled() || _context.getBooleanProperty(PROP_IPV6_FIREWALLED)) {
|
||||||
// change to firewalled maybe? but we don't have any test to restore
|
setReachabilityStatus(Status.IPV4_UNKNOWN_IPV6_FIREWALLED, true);
|
||||||
// a v6 address after it's removed.
|
} else {
|
||||||
_lastInboundIPv6 = _context.clock().now();
|
_lastInboundIPv6 = _context.clock().now();
|
||||||
if (!isIPv6Firewalled())
|
|
||||||
setReachabilityStatus(Status.IPV4_UNKNOWN_IPV6_OK, true);
|
setReachabilityStatus(Status.IPV4_UNKNOWN_IPV6_OK, true);
|
||||||
|
rebuildExternalAddress(ia.getHostAddress(), newPort, false);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!isIPv4Firewalled())
|
if (!isIPv4Firewalled())
|
||||||
setReachabilityStatus(Status.IPV4_OK_IPV6_UNKNOWN);
|
setReachabilityStatus(Status.IPV4_OK_IPV6_UNKNOWN);
|
||||||
|
rebuildExternalAddress(ia.getHostAddress(), newPort, false);
|
||||||
}
|
}
|
||||||
rebuildExternalAddress(ia.getHostAddress(), newPort, false);
|
|
||||||
}
|
}
|
||||||
} else if (newPort > 0 && !bindToAddrs.isEmpty()) {
|
} else if (newPort > 0 && !bindToAddrs.isEmpty()) {
|
||||||
for (InetAddress ia : bindToAddrs) {
|
for (InetAddress ia : bindToAddrs) {
|
||||||
@ -595,6 +633,12 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
|||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void shutdown() {
|
public synchronized void shutdown() {
|
||||||
|
if (_haveIPv6Address) {
|
||||||
|
boolean fwOld = _context.getBooleanProperty(PROP_IPV6_FIREWALLED);
|
||||||
|
boolean fwNew = STATUS_IPV6_FW.contains(_reachabilityStatus);
|
||||||
|
if (fwOld != fwNew)
|
||||||
|
_context.router().saveConfig(PROP_IPV6_FIREWALLED, Boolean.toString(fwNew));
|
||||||
|
}
|
||||||
destroyAll();
|
destroyAll();
|
||||||
for (UDPEndpoint endpoint : _endpoints) {
|
for (UDPEndpoint endpoint : _endpoints) {
|
||||||
endpoint.shutdown();
|
endpoint.shutdown();
|
||||||
@ -1051,11 +1095,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
|||||||
_log.info("New IPv6 address received but not one of our local addresses: " + ipstr, new Exception());
|
_log.info("New IPv6 address received but not one of our local addresses: " + ipstr, new Exception());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (_reachabilityStatus == Status.IPV4_OK_IPV6_FIREWALLED ||
|
if (STATUS_IPV6_FW_2.contains(_reachabilityStatus)) {
|
||||||
_reachabilityStatus == Status.IPV4_UNKNOWN_IPV6_FIREWALLED ||
|
|
||||||
_reachabilityStatus == Status.IPV4_DISABLED_IPV6_FIREWALLED ||
|
|
||||||
_reachabilityStatus == Status.DIFFERENT ||
|
|
||||||
_reachabilityStatus == Status.REJECT_UNSOLICITED) {
|
|
||||||
// If we were firewalled before, let's assume we're still firewalled.
|
// If we were firewalled before, let's assume we're still firewalled.
|
||||||
// Save the new IP and fire a test
|
// Save the new IP and fire a test
|
||||||
String oldIP = _context.getProperty(PROP_IPV6);
|
String oldIP = _context.getProperty(PROP_IPV6);
|
||||||
@ -1217,9 +1257,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
|||||||
if (prop != null)
|
if (prop != null)
|
||||||
return Boolean.parseBoolean(prop);
|
return Boolean.parseBoolean(prop);
|
||||||
Status status = getReachabilityStatus();
|
Status status = getReachabilityStatus();
|
||||||
return status != Status.REJECT_UNSOLICITED &&
|
return !STATUS_NEED_INTRO.contains(status);
|
||||||
status != Status.IPV4_FIREWALLED_IPV6_OK &&
|
|
||||||
status != Status.IPV4_FIREWALLED_IPV6_UNKNOWN;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1450,13 +1488,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
|||||||
synchronized(_rebuildLock) {
|
synchronized(_rebuildLock) {
|
||||||
rebuildIfNecessary();
|
rebuildIfNecessary();
|
||||||
Status status = getReachabilityStatus();
|
Status status = getReachabilityStatus();
|
||||||
if (status != Status.OK &&
|
if (!STATUS_NO_RETEST.contains(status) &&
|
||||||
status != Status.IPV4_OK_IPV6_UNKNOWN &&
|
|
||||||
status != Status.IPV4_OK_IPV6_FIREWALLED &&
|
|
||||||
status != Status.IPV4_DISABLED_IPV6_OK &&
|
|
||||||
status != Status.IPV4_DISABLED_IPV6_UNKNOWN &&
|
|
||||||
status != Status.IPV4_DISABLED_IPV6_FIREWALLED &&
|
|
||||||
status != Status.DISCONNECTED &&
|
|
||||||
_reachabilityStatusUnchanged < 7) {
|
_reachabilityStatusUnchanged < 7) {
|
||||||
_testEvent.forceRunSoon(peer.isIPv6());
|
_testEvent.forceRunSoon(peer.isIPv6());
|
||||||
}
|
}
|
||||||
@ -3063,16 +3095,8 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
|||||||
if (status != old) {
|
if (status != old) {
|
||||||
// for the following transitions ONLY, require two in a row
|
// for the following transitions ONLY, require two in a row
|
||||||
// to prevent thrashing
|
// to prevent thrashing
|
||||||
if ((old == Status.OK && (status == Status.DIFFERENT ||
|
if ((old == Status.OK && STATUS_IPV4_FW.contains(status)) ||
|
||||||
status == Status.REJECT_UNSOLICITED ||
|
(status == Status.OK && STATUS_IPV4_FW.contains(old))) {
|
||||||
status == Status.IPV4_FIREWALLED_IPV6_OK ||
|
|
||||||
status == Status.IPV4_SNAT_IPV6_OK ||
|
|
||||||
status == Status.IPV4_OK_IPV6_FIREWALLED)) ||
|
|
||||||
(status == Status.OK && (old == Status.DIFFERENT ||
|
|
||||||
old == Status.REJECT_UNSOLICITED ||
|
|
||||||
old == Status.IPV4_FIREWALLED_IPV6_OK ||
|
|
||||||
old == Status.IPV4_SNAT_IPV6_OK ||
|
|
||||||
old == Status.IPV4_OK_IPV6_FIREWALLED))) {
|
|
||||||
if (status != _reachabilityStatusPending) {
|
if (status != _reachabilityStatusPending) {
|
||||||
if (_log.shouldLog(Log.WARN))
|
if (_log.shouldLog(Log.WARN))
|
||||||
_log.warn("Old status: " + old + " status pending confirmation: " + status +
|
_log.warn("Old status: " + old + " status pending confirmation: " + status +
|
||||||
@ -3103,18 +3127,10 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
|||||||
// as rebuildExternalAddress() calls replaceAddress() which calls CSFI.notifyReplaceAddress()
|
// as rebuildExternalAddress() calls replaceAddress() which calls CSFI.notifyReplaceAddress()
|
||||||
// which will start up NTCP inbound when we transition to OK.
|
// which will start up NTCP inbound when we transition to OK.
|
||||||
if (isIPv6) {
|
if (isIPv6) {
|
||||||
if (status == Status.IPV4_OK_IPV6_FIREWALLED ||
|
if (STATUS_IPV6_FW.contains(status)) {
|
||||||
status == Status.IPV4_UNKNOWN_IPV6_FIREWALLED ||
|
|
||||||
status == Status.IPV4_DISABLED_IPV6_FIREWALLED) {
|
|
||||||
removeExternalAddress(true, true);
|
removeExternalAddress(true, true);
|
||||||
} else if ((old == Status.IPV4_OK_IPV6_FIREWALLED ||
|
} else if (STATUS_IPV6_FW.contains(old) &&
|
||||||
old == Status.IPV4_UNKNOWN_IPV6_FIREWALLED ||
|
STATUS_IPV6_OK.contains(status) &&
|
||||||
old == Status.IPV4_DISABLED_IPV6_FIREWALLED) &&
|
|
||||||
(status == Status.OK ||
|
|
||||||
status == Status.IPV4_UNKNOWN_IPV6_OK ||
|
|
||||||
status == Status.IPV4_FIREWALLED_IPV6_OK ||
|
|
||||||
status == Status.IPV4_DISABLED_IPV6_OK ||
|
|
||||||
status == Status.IPV4_SNAT_IPV6_OK) &&
|
|
||||||
_lastOurIPv6 != null &&
|
_lastOurIPv6 != null &&
|
||||||
!explicitAddressSpecified()){
|
!explicitAddressSpecified()){
|
||||||
String addr = Addresses.toString(_lastOurIPv6);
|
String addr = Addresses.toString(_lastOurIPv6);
|
||||||
|
Reference in New Issue
Block a user