diff --git a/app/src/main/java/eu/faircode/netguard/ServiceSinkhole.java b/app/src/main/java/eu/faircode/netguard/ServiceSinkhole.java index 046eccd6..d1523290 100644 --- a/app/src/main/java/eu/faircode/netguard/ServiceSinkhole.java +++ b/app/src/main/java/eu/faircode/netguard/ServiceSinkhole.java @@ -148,7 +148,7 @@ public class ServiceSinkhole extends VpnService implements SharedPreferences.OnS private Map mapHostsBlocked = new HashMap<>(); private Map mapUidAllowed = new HashMap<>(); private Map mapUidKnown = new HashMap<>(); - private final Map> mapUidIPFilters = new HashMap<>(); + private final Map> mapUidIPFilters = new HashMap<>(); private Map mapForward = new HashMap<>(); private Map mapNotify = new HashMap<>(); private ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true); @@ -1592,15 +1592,7 @@ public class ServiceSinkhole extends VpnService implements SharedPreferences.OnS } } - // long is 64 bits - // 0..15 uid - // 16..31 dport - // 32..39 protocol - // 40..43 version - if (!(protocol == 6 /* TCP */ || protocol == 17 /* UDP */)) - dport = 0; - long key = (version << 40) | (protocol << 32) | (dport << 16) | uid; - + IPKey key = new IPKey(version, protocol, dport, uid); synchronized (mapUidIPFilters) { if (!mapUidIPFilters.containsKey(key)) mapUidIPFilters.put(key, new HashMap()); @@ -1615,17 +1607,17 @@ public class ServiceSinkhole extends VpnService implements SharedPreferences.OnS continue; //if (dname != null) - Log.i(TAG, "Set filter uid=" + uid + " " + daddr + " " + dresource + "/" + dport + "=" + block); + Log.i(TAG, "Set filter " + key + " " + daddr + "/" + dresource + "=" + block); boolean exists = mapUidIPFilters.get(key).containsKey(iname); if (!exists || !mapUidIPFilters.get(key).get(iname).isBlocked()) { - IPRule rule = new IPRule(name + "/" + iname, block, time + ttl); + IPRule rule = new IPRule(key, name + "/" + iname, block, time + ttl); mapUidIPFilters.get(key).put(iname, rule); if (exists) - Log.w(TAG, "Address conflict uid=" + uid + " " + daddr + " " + dresource + "/" + dport); + Log.w(TAG, "Address conflict " + key + " " + daddr + "/" + dresource); } else if (exists) { mapUidIPFilters.get(key).get(iname).updateExpires(time + ttl); - Log.w(TAG, "Address updated uid=" + uid + " " + daddr + " " + dresource + "/" + dport); + Log.w(TAG, "Address updated " + key + " " + daddr + "/" + dresource); } } else Log.w(TAG, "Address not numeric " + name); @@ -1852,10 +1844,7 @@ public class ServiceSinkhole extends VpnService implements SharedPreferences.OnS Log.w(TAG, "Allowing self " + packet); } else { boolean filtered = false; - // Only TCP (6) and UDP (17) have port numbers - int dport = (packet.protocol == 6 || packet.protocol == 17 ? packet.dport : 0); - long key = (packet.version << 40) | (packet.protocol << 32) | (dport << 16) | packet.uid; - + IPKey key = new IPKey(packet.version, packet.protocol, packet.dport, packet.uid); if (mapUidIPFilters.containsKey(key)) try { InetAddress iaddr = InetAddress.getByName(packet.daddr); @@ -3057,12 +3046,50 @@ public class ServiceSinkhole extends VpnService implements SharedPreferences.OnS } } + private class IPKey { + int version; + int protocol; + int dport; + int uid; + + public IPKey(int version, int protocol, int dport, int uid) { + this.version = version; + this.protocol = protocol; + // Only TCP (6) and UDP (17) have port numbers + this.dport = (protocol == 6 || protocol == 17 ? dport : 0); + this.uid = uid; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof IPKey)) + return false; + IPKey other = (IPKey) obj; + return (this.version == other.version && + this.protocol == other.protocol && + this.dport == other.dport && + this.uid == other.uid); + } + + @Override + public int hashCode() { + return (version << 40) | (protocol << 32) | (dport << 16) | uid; + } + + @Override + public String toString() { + return "v" + version + " p" + protocol + " port=" + dport + " uid=" + uid; + } + } + private class IPRule { + private IPKey key; private String name; private boolean block; private long expires; - public IPRule(String name, boolean block, long expires) { + public IPRule(IPKey key, String name, boolean block, long expires) { + this.key = key; this.name = name; this.block = block; this.expires = expires; @@ -3088,7 +3115,7 @@ public class ServiceSinkhole extends VpnService implements SharedPreferences.OnS @Override public String toString() { - return this.name; + return this.key + " " + this.name; } }