forked from I2P_Developers/i2p.i2p
Profiles: Don't use same family in a tunnel
Reduce IPv6 mask from 8 to 6
This commit is contained in:
@@ -17,7 +17,7 @@ import java.util.TreeSet;
|
|||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
|
|
||||||
import net.i2p.crypto.SHA256Generator;
|
import net.i2p.data.DataHelper;
|
||||||
import net.i2p.data.Hash;
|
import net.i2p.data.Hash;
|
||||||
import net.i2p.data.router.RouterAddress;
|
import net.i2p.data.router.RouterAddress;
|
||||||
import net.i2p.data.router.RouterInfo;
|
import net.i2p.data.router.RouterInfo;
|
||||||
@@ -1234,12 +1234,15 @@ public class ProfileOrganizer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
*
|
||||||
|
* As of 0.9.24, checks for a netdb family match as well, unless mask == 0.
|
||||||
|
*
|
||||||
* @param mask 0-4 Number of bytes to match to determine if peers in the same IP range should
|
* @param mask 0-4 Number of bytes to match to determine if peers in the same IP range should
|
||||||
* not be in the same tunnel. 0 = disable check; 1 = /8; 2 = /16; 3 = /24; 4 = exact IP match
|
* not be in the same tunnel. 0 = disable check; 1 = /8; 2 = /16; 3 = /24; 4 = exact IP match
|
||||||
*/
|
*/
|
||||||
private void locked_selectPeers(Map<Hash, PeerProfile> peers, int howMany, Set<Hash> toExclude, Set<Hash> matches, int mask) {
|
private void locked_selectPeers(Map<Hash, PeerProfile> peers, int howMany, Set<Hash> toExclude, Set<Hash> matches, int mask) {
|
||||||
List<Hash> all = new ArrayList<Hash>(peers.keySet());
|
List<Hash> all = new ArrayList<Hash>(peers.keySet());
|
||||||
Set<Integer> IPSet = new HashSet<Integer>(8);
|
Set<String> IPSet = new HashSet<String>(8);
|
||||||
// use RandomIterator to avoid shuffling the whole thing
|
// use RandomIterator to avoid shuffling the whole thing
|
||||||
for (Iterator<Hash> iter = new RandomIterator<Hash>(all); (matches.size() < howMany) && iter.hasNext(); ) {
|
for (Iterator<Hash> iter = new RandomIterator<Hash>(all); (matches.size() < howMany) && iter.hasNext(); ) {
|
||||||
Hash peer = iter.next();
|
Hash peer = iter.next();
|
||||||
@@ -1265,11 +1268,14 @@ public class ProfileOrganizer {
|
|||||||
/**
|
/**
|
||||||
* Does the peer's IP address NOT match the IP address of any peer already in the set,
|
* Does the peer's IP address NOT match the IP address of any peer already in the set,
|
||||||
* on any transport, within a given mask?
|
* on any transport, within a given mask?
|
||||||
|
*
|
||||||
|
* As of 0.9.24, checks for a netdb family match as well.
|
||||||
|
*
|
||||||
* @param mask is 1-4 (number of bytes to match)
|
* @param mask is 1-4 (number of bytes to match)
|
||||||
* @param IPMatches all IPs so far, modified by this routine
|
* @param IPMatches all IPs so far, modified by this routine
|
||||||
*/
|
*/
|
||||||
private boolean notRestricted(Hash peer, Set<Integer> IPSet, int mask) {
|
private boolean notRestricted(Hash peer, Set<String> IPSet, int mask) {
|
||||||
Set<Integer> peerIPs = maskedIPSet(peer, mask);
|
Set<String> peerIPs = maskedIPSet(peer, mask);
|
||||||
if (containsAny(IPSet, peerIPs))
|
if (containsAny(IPSet, peerIPs))
|
||||||
return false;
|
return false;
|
||||||
IPSet.addAll(peerIPs);
|
IPSet.addAll(peerIPs);
|
||||||
@@ -1280,10 +1286,12 @@ public class ProfileOrganizer {
|
|||||||
* The Set of IPs for this peer, with a given mask.
|
* The Set of IPs for this peer, with a given mask.
|
||||||
* Includes the comm system's record of the IP, and all netDb addresses.
|
* Includes the comm system's record of the IP, and all netDb addresses.
|
||||||
*
|
*
|
||||||
|
* As of 0.9.24, returned set will include netdb family as well.
|
||||||
|
*
|
||||||
* @return an opaque set of masked IPs for this peer
|
* @return an opaque set of masked IPs for this peer
|
||||||
*/
|
*/
|
||||||
private Set<Integer> maskedIPSet(Hash peer, int mask) {
|
private Set<String> maskedIPSet(Hash peer, int mask) {
|
||||||
Set<Integer> rv = new HashSet<Integer>(4);
|
Set<String> rv = new HashSet<String>(4);
|
||||||
byte[] commIP = _context.commSystem().getIP(peer);
|
byte[] commIP = _context.commSystem().getIP(peer);
|
||||||
if (commIP != null)
|
if (commIP != null)
|
||||||
rv.add(maskedIP(commIP, mask));
|
rv.add(maskedIP(commIP, mask));
|
||||||
@@ -1296,31 +1304,40 @@ public class ProfileOrganizer {
|
|||||||
if (pib == null) continue;
|
if (pib == null) continue;
|
||||||
rv.add(maskedIP(pib, mask));
|
rv.add(maskedIP(pib, mask));
|
||||||
}
|
}
|
||||||
|
String family = pinfo.getOption("family");
|
||||||
|
if (family != null) {
|
||||||
|
// TODO should KNDF put a family-verified indicator in the RI,
|
||||||
|
// after checking the sig, or does it matter?
|
||||||
|
// What's the threat here of not avoid ding a router
|
||||||
|
// falsely claiming to be in the family?
|
||||||
|
// Prefix with something so an IP can't be spoofed
|
||||||
|
rv.add('x' + family);
|
||||||
|
}
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* generate an arbitrary unique value for this ip/mask (mask = 1-4)
|
* generate an arbitrary unique value for this ip/mask (mask = 1-4)
|
||||||
* If IPv6, force mask = 8.
|
* If IPv6, force mask = 6.
|
||||||
*/
|
*/
|
||||||
private static Integer maskedIP(byte[] ip, int mask) {
|
private static String maskedIP(byte[] ip, int mask) {
|
||||||
int rv = ip[0];
|
final StringBuilder buf = new StringBuilder(1 + (mask*2));
|
||||||
|
final char delim;
|
||||||
if (ip.length == 16) {
|
if (ip.length == 16) {
|
||||||
for (int i = 1; i < 8; i++) {
|
mask = 6;
|
||||||
rv <<= i * 4;
|
delim = ':';
|
||||||
rv ^= ip[i];
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
for (int i = 1; i < mask; i++) {
|
delim = '.';
|
||||||
rv <<= 8;
|
|
||||||
rv ^= ip[i];
|
|
||||||
}
|
}
|
||||||
}
|
buf.append(delim);
|
||||||
return Integer.valueOf(rv);
|
buf.append(Long.toHexString(DataHelper.fromLong(ip, 0, mask)));
|
||||||
|
return buf.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** does a contain any of the elements in b? */
|
/** does a contain any of the elements in b? */
|
||||||
private static <T> boolean containsAny(Set<T> a, Set<T> b) {
|
private static <T> boolean containsAny(Set<T> a, Set<T> b) {
|
||||||
|
if (a.isEmpty() || b.isEmpty())
|
||||||
|
return false;
|
||||||
for (T o : b) {
|
for (T o : b) {
|
||||||
if (a.contains(o))
|
if (a.contains(o))
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
Reference in New Issue
Block a user