Commit d502c49b authored by Max Lv's avatar Max Lv

fix #40

parent fadea49c
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
package be.jvb.iptypes
import java.net.InetAddress
/**
* Represents an IPv4 address.
*
* @author <a href="http://janvanbesien.blogspot.com">Jan Van Besien</a>
*
* @param value 32bit value of the ip address (only 32 least significant bits are used)
*/
class IpAddress(val value: Long) extends SmallByteArray {
/**
* Construct from a CIDR format string representation (e.g. "192.168.0.1").
*/
def this(address: String) = this (SmallByteArray.parseAsLong(address, IpAddress.N_BYTES, DEC()))
/**
* Construct from a java.net.InetAddress.
*/
def this(inetAddress: InetAddress) = {
this (if (inetAddress == null) throw new IllegalArgumentException("can not create from [null]") else inetAddress
.getHostAddress)
}
protected def nBytes = IpAddress.N_BYTES
protected def radix = DEC()
/**
* Addition. Will never overflow, but wraps around when the highest ip address has been reached.
*/
def +(value: Long) = new IpAddress((this.value + value) & maxValue)
/**
* Substraction. Will never underflow, but wraps around when the lowest ip address has been reached.
*/
def -(value: Long) = new IpAddress((this.value - value) & maxValue)
/**
* Convert to java.net.InetAddress.
*/
def toInetAddress: InetAddress = InetAddress.getByName(toString)
}
object IpAddress {
val N_BYTES = 4
def apply(string: String): IpAddress = new IpAddress(SmallByteArray.parseAsLong(string, N_BYTES, DEC()))
def unapply(ipAddress: IpAddress): Option[String] = {
Some(ipAddress.toString)
}
}
package be.jvb.iptypes
import scala.collection.immutable._
import scala.collection.mutable.ListBuffer
/**
* Represents a pool of IPv4 addresses. A pool is a range of addresses, from which some can be "allocated" and some can be
* "free".
*
* @author <a href="http://janvanbesien.blogspot.com">Jan Van Besien</a>
*
* @param first first address in the pool
* @param last last address in the pool
* @param freeRanges sorted set of all free ranges in this pool. All free ranges should be contained in the range from first to last;
* none of the free ranges should overlap; and the set of free ranges should contain as little fragments as necessary.
*/
class IpAddressPool private(override val first: IpAddress, override val last: IpAddress, val freeRanges: SortedSet[IpAddressRange])
extends IpAddressRange(first, last) {
validateFreeRanges(freeRanges)
/**
* Construct a pool which is completely free.
*/
def this(first: IpAddress, last: IpAddress) = {
// the whole ranges is free initially
this (first, last, TreeSet[IpAddressRange](new IpAddressRange(first, last)))
}
/**
* Construct a pool which is completely free from an existing address range.
*/
def this(range: IpAddressRange) = {
this (range.first, range.last)
}
private def validateFreeRanges(toValidate: SortedSet[IpAddressRange]) = {
if (!toValidate.isEmpty && !checkWithinBounds(toValidate))
throw new IllegalArgumentException("invalid free ranges: not all within pool range")
}
private def checkWithinBounds(toValidate: SortedSet[IpAddressRange]): Boolean = {
return (toValidate.firstKey.first >= first && toValidate.lastKey.last <= last)
}
/**
* Allocate the first free address in the pool.
*
* @returns the pool after allocation and the allocated address (or None if no address was free)
*/
def allocate(): (IpAddressPool, Option[IpAddress]) = {
if (!isExhausted) {
// get the first range of free addresses, and take the first address of that range
val range: IpAddressRange = freeRanges.firstKey
val toAllocate: IpAddress = range.first
return doAllocate(toAllocate, range)
} else {
return (this, None)
}
}
/**
* Allocate the given address in the pool.
*
* @param toAllocate address to allocate in the pool
* @returns the pool after allocation and the allocated address (or None if the address was not free in this pool)
*/
def allocate(toAllocate: IpAddress): (IpAddressPool, Option[IpAddress]) = {
if (!contains(toAllocate))
throw new IllegalArgumentException("can not allocate address which is not contained in the range of the pool [" + toAllocate + "]")
// go find the range that contains the requested address
findFreeRangeContaining(toAllocate) match {
case Some(range) => doAllocate(toAllocate, range) // allocate in the range we found
case None => {
(this, None) // no free range found for the requested address
}
}
}
private def findFreeRangeContaining(toAllocate: IpAddress): Option[IpAddressRange] = {
// split around the address to allocate
val head = freeRanges.until(new IpAddressRange(toAllocate, toAllocate))
val tail = freeRanges.from(new IpAddressRange(toAllocate, toAllocate))
// the range we need is either the first of the tail, or the last of the head, or it doesn't exist
if (!head.isEmpty && head.lastKey.contains(toAllocate)) {
return Some(head.lastKey)
}
else if (!tail.isEmpty && tail.firstKey.contains(toAllocate)) {
return Some(tail.firstKey)
}
else {
return None
}
}
/**
* Allocate the given address in the given range. It is assumed at this point that the range actually contains
* the address, and that the range is one of the free ranges of the pool.
*/
private def doAllocate(toAllocate: IpAddress, range: IpAddressRange): (IpAddressPool, Option[IpAddress]) = {
// remove the range and replace with ranges without the allocated address
val newRanges = range - toAllocate
// note: the cast to SortedSet is a workaround until scala 2.8 (http://stackoverflow.com/questions/1271426/scala-immutable-sortedset-are-not-stable-on-deletion)
val remainingRanges = (freeRanges ++ newRanges).asInstanceOf[SortedSet[IpAddressRange]] - range
return (new IpAddressPool(this.first, this.last, remainingRanges.asInstanceOf[SortedSet[IpAddressRange]]), Some(toAllocate))
}
/**
* Deallocate the given address in the pool. The given address will be free in the returned pool.
*
* @returns the pool after deallocation
*/
def deAllocate(address: IpAddress): IpAddressPool = {
if (!contains(address))
throw new IllegalArgumentException("can not deallocate address which is not contained in the range of the pool [" + address + "]")
return new IpAddressPool(first, last, addAddressToFreeRanges(address))
}
/**
* Add the given address as a free address in the set of free ranges. The implementation tries to merge existing ranges
* as much as possible to prevent fragmentation.
*/
private def addAddressToFreeRanges(address: IpAddress): SortedSet[IpAddressRange] = {
val freeRangeBeforeAddress: Iterable[IpAddressRange] = freeRanges.filter(element => element.last + 1 == address)
val freeRangeAfterAddress: Iterable[IpAddressRange] = freeRanges.filter(element => element.first - 1 == address)
if (freeRangeBeforeAddress.isEmpty && freeRangeAfterAddress.isEmpty) {
// no match -> nothing to "defragment"
return freeRanges + new IpAddressRange(address, address)
} else {
if (!freeRangeBeforeAddress.isEmpty && !freeRangeAfterAddress.isEmpty) {
// first and last match -> merge the 2 existing ranges
return (freeRanges -
freeRangeBeforeAddress.toSeq(0) -
freeRangeAfterAddress.toSeq(0) +
new IpAddressRange(freeRangeBeforeAddress.toSeq(0).first, freeRangeAfterAddress.toSeq(0).last)).
asInstanceOf[SortedSet[IpAddressRange]] // workaround, see above
} else if (!freeRangeBeforeAddress.isEmpty) {
// append
return (freeRanges -
freeRangeBeforeAddress.toSeq(0) +
(freeRangeBeforeAddress.toSeq(0) + address)).
asInstanceOf[SortedSet[IpAddressRange]] // workaround, see above
} else {
// prepend
return (freeRanges -
freeRangeAfterAddress.toSeq(0) +
(freeRangeAfterAddress.toSeq(0) + address)).
asInstanceOf[SortedSet[IpAddressRange]] // workaround, see above
}
}
}
def isExhausted(): Boolean = {
freeRanges.isEmpty
}
def isFree(address: IpAddress): Boolean = {
// lookup the address in all free ranges, if true in one, the result is true
freeRanges.map(_ contains address).reduceLeft((x, y) => x || y)
}
/**
* @return the number of free ranges fragments
*/
def fragments(): Int = {
freeRanges.size
}
/**
* @return a stream of all free addresses in the pool
*/
def freeAddresses(): Stream[IpAddress] = {
toAddressesStream(freeRanges.toList)
}
/**
* @return a stream of all allocated addresses in the pool
*/
def allocatedAddresses(): Stream[IpAddress] = {
toAddressesStream(allocatedRanges.toList)
}
/**
* @return ranges of allocated addresses in the pool
* @note the pool implementation keeps track of the free addresses, so this operation is more expensive than the freeRanges() one
*/
def allocatedRanges(): List[IpAddressRange] = {
if (freeRanges.isEmpty) {
// one big range of allocated addresses
List[IpAddressRange](new IpAddressRange(first, last))
} else {
makeNonEmptyListOfAllocatedRanges()
}
}
private def makeNonEmptyListOfAllocatedRanges(): List[IpAddressRange] = {
val allocatedRanges: ListBuffer[IpAddressRange] = new ListBuffer[IpAddressRange]()
var currentStart: IpAddress = first
var currentEnd: IpAddress = null
for (freeRange <- freeRanges) {
currentEnd = freeRange.first
if (currentEnd != currentStart) { // occurs if first free range starts at the beginning of the pool
allocatedRanges + new IpAddressRange(currentStart, currentEnd - 1)
}
currentStart = freeRange.last + 1
}
if (currentStart <= last) { // occurs if the last free range didn't reach until the end of the pool
allocatedRanges + new IpAddressRange(currentStart, last)
}
return allocatedRanges.toList
}
// /**
// * @return ranges of free addresses in the pool
// */
// def freeRanges(): SortedSet[IpAddressRange] = freeRanges
private def toAddressesStream(ranges: List[IpAddressRange]): Stream[IpAddress] = {
if (ranges.isEmpty) {
Stream.empty
} else {
Stream.concat(ranges.head.addresses, toAddressesStream(ranges.tail))
}
}
override def toString(): String = {
"IpAddressPool " + super.toString + " with free ranges " + freeRanges.toString
}
// TODO: toStringRepresentation which can also be parsed back into an IpAddressPool
// equals implemented as suggested in staircase book
override def equals(other: Any): Boolean = {
other match {
case that: IpAddressPool => super.equals(that) && this.freeRanges == that.freeRanges
case _ => false
}
}
protected override def canEqual(other: Any): Boolean = {
other.isInstanceOf[IpAddressPool]
}
override def hashCode = {
41 * (41 + first.hashCode) + last.hashCode
}
}
\ No newline at end of file
package be.jvb.iptypes
import scala.math.Ordered
/**
* Represents a continuous range of IPv4 ip addresses (bounds included).
*
* @author <a href="http://janvanbesien.blogspot.com">Jan Van Besien</a>
*
* @param first first address in the range
* @param last last address in the range
*/
class IpAddressRange(val first: IpAddress, val last: IpAddress) extends Ordered[IpAddressRange] {
if (last < first)
throw new IllegalArgumentException("Cannot create ip address range with last address > first address")
def contains(address: IpAddress): Boolean = {
address >= first && address <= last
}
def contains(range: IpAddressRange): Boolean = {
contains(range.first) && contains(range.last)
}
def overlaps(range: IpAddressRange): Boolean = {
contains(range.first) || contains(range.last) || range.contains(first) || range.contains(last)
}
def length = {
last.value - first.value + 1
}
def addresses(): Stream[IpAddress] = {
if (first < last) {
Stream.cons(first, new IpAddressRange(first + 1, last).addresses())
} else {
Stream.cons(first, Stream.empty)
}
}
/**
* Ip address ranges are ordered on the first address, or on the second address if the first is equal.
*/
def compare(that: IpAddressRange): Int = {
if (this.first != that.first)
this.first.compare(that.first)
else
this.last.compare(that.last)
}
/**
* Remove an address from the range, resulting in one, none or two new ranges.
*/
def -(address: IpAddress): List[IpAddressRange] = {
if (address eq null)
throw new IllegalArgumentException("invalid address [null]")
if (!contains(address))
List(this)
else if (address == first && address == last)
List()
else if (address == first)
List(new IpAddressRange(first + 1, last))
else if (address == last)
List(new IpAddressRange(first, last - 1))
else
List(new IpAddressRange(first, address - 1), new IpAddressRange(address + 1, last))
}
/**
* Extend the range just enough at its head or tail such that the given address is included.
*/
def +(address: IpAddress): IpAddressRange = {
if (address < first)
new IpAddressRange(address, last)
else if (address > last)
new IpAddressRange(first, address)
else
this
}
override def toString: String = {
first.toString + " - " + last.toString
}
// equals implemented as suggested in staircase book
override def equals(other: Any): Boolean = {
other match {
case that: IpAddressRange => that.canEqual(this) && this.first == that.first && this.last == that.last
case _ => false
}
}
protected def canEqual(other: Any): Boolean = {
other.isInstanceOf[IpAddressRange]
}
override def hashCode = {
41 * (41 + first.hashCode) + last.hashCode
}
}
package be.jvb.iptypes
import java.lang.String
/**
* Represents an Ipv4 network (i.e. an address and a mask).
*
* @author <a href="http://janvanbesien.blogspot.com">Jan Van Besien</a>
*
* @param address network address of the network
* @param mask network mask of the network
*/
class IpNetwork(val address: IpAddress, val mask: IpNetworkMask)
extends IpAddressRange(IpNetwork.first(address, mask), IpNetwork.last(address, mask)) {
/**
* Construct a network from two addresses. This will create the smallest possible network ("longest prefix match") which contains
* both addresses.
*/
def this(first: IpAddress, last: IpAddress) = this (first, IpNetworkMask.longestPrefixNetwork(first, last))
private def this(addressAndMask: (IpAddress, IpNetworkMask)) = this (addressAndMask._1, addressAndMask._2)
/**
* Construct a network from a CIDR notation (e.g. "192.168.0.0/24" or "192.168.0.0/255.255.255.0")
*/
def this(network: String) = this (IpNetwork.parseAddressAndMaskFromCidrNotation(network))
/**
* @return CIDR notation
*/
override def toString: String = first.toString + "/" + mask.prefixLength
}
object IpNetwork {
/**
* get the first address from a network which contains the given address.
*/
private[iptypes] def first(address: IpAddress, mask: IpNetworkMask): IpAddress = {
new IpAddress(address.value & mask.value)
}
/**
* get the last address from a network which contains the given address.
*/
private[iptypes] def last(address: IpAddress, mask: IpNetworkMask): IpAddress = {
first(address, mask) + (0xFFFFFFFFL >> mask.prefixLength)
}
private[iptypes] def parseAddressAndMaskFromCidrNotation(cidrString: String): (IpAddress, IpNetworkMask) = {
if (!cidrString.contains("/"))
throw new IllegalArgumentException("no CIDR format [" + cidrString + "]")
val addressAndMask: (String, String) = splitInAddressAndMask(cidrString)
val address = new IpAddress(addressAndMask._1)
val mask = parseNetworkMask(addressAndMask._2)
(address, mask)
}
private def splitInAddressAndMask(cidrString: String): (String, String) = {
val addressAndMask: Array[String] = cidrString.split("/")
if (addressAndMask.length != 2)
throw new IllegalArgumentException("no CIDR format [" + cidrString + "]")
(addressAndMask(0), addressAndMask(1))
}
private def parseNetworkMask(mask: String) = {
try
{
if (mask.contains("."))
new IpNetworkMask(mask)
else
IpNetworkMask.fromPrefixLength(Integer.parseInt(mask))
} catch {
case e: Exception => throw new IllegalArgumentException("not a valid network mask [" + mask + "]", e)
}
}
}
\ No newline at end of file
package be.jvb.iptypes
import java.lang.IllegalArgumentException
/**
* Represents an IPv4 network mask.
*
* @author <a href="http://janvanbesien.blogspot.com">Jan Van Besien</a>
*/
class IpNetworkMask(override val value: Long) extends IpAddress(value) {
def this(address: String) = this (SmallByteArray.parseAsLong(address, IpAddress.N_BYTES, DEC()))
checkMaskValidity()
private def checkMaskValidity() = {
if (!IpNetworkMask.VALID_MASK_VALUES.contains(value))
throw new IllegalArgumentException("Not a valid ip network mask [" + this + "]")
}
def prefixLength = {
IpNetworkMask.fromLongToPrefixLength(value)
}
}
object IpNetworkMask {
private[iptypes] val VALID_MASK_VALUES = for (prefixLength <- 0 to 32) yield fromPrefixLenthToLong(
prefixLength)
/**
* Convert a prefix length (e.g. 24) into a network mask (e.g. 255.255.255.0). IpNetworkMask hasn't got a public constructor for this, because
* it would be confusing with the constructor that takes a long.
*/
def fromPrefixLength(prefixLength: Int): IpNetworkMask = {
new IpNetworkMask(fromPrefixLenthToLong(prefixLength))
}
private[iptypes] def fromPrefixLenthToLong(prefixLength: Int): Long = {
(((1L << 32) - 1) << (32 - prefixLength)) & 0xFFFFFFFFL
}
private[iptypes] def fromLongToPrefixLength(value: Long): Int = {
val lsb: Long = value & 0xFFFFFFFFL
var result: Int = 0
var bit: Long = 1L << 31
while (((lsb & bit) != 0) && (result < 32)) {
bit = bit >> 1
result += 1
}
result
}
/**
* Construct a network mask which has the longest matching prefix to still contain both given addresses.
*/
def longestPrefixNetwork(first: IpAddress, last: IpAddress): IpNetworkMask = {
IpNetworkMask.fromPrefixLength(IpNetworkMask.fromLongToPrefixLength(~first.value ^ last.value))
}
def apply(string: String): IpNetworkMask = new IpNetworkMask(SmallByteArray.parseAsLong(string, IpAddress.N_BYTES, DEC()))
def unapply(ipNetworkMask: IpNetworkMask): Option[String] = {
Some(ipNetworkMask.toString)
}
}
\ No newline at end of file
package be.jvb.iptypes
/**
* Represents a MAC address.
*
* @author <a href="http://janvanbesien.blogspot.com">Jan Van Besien</a>
*/
class MacAddress(val value: Long) extends SmallByteArray {
def this(address: String) = this(SmallByteArray.parseAsLong(address, MacAddress.N_BYTES, HEX()))
protected def nBytes = MacAddress.N_BYTES
protected def radix = HEX()
override def zeroPaddingUpTo = 2
/**
* Addition. Will never overflow, but wraps around when the highest MAC address has been reached.
*/
def +(value: Long) = new MacAddress((this.value + value) & maxValue)
/**
* Substraction. Will never underflow, but wraps around when the lowest MAC address has been reached.
*/
def -(value: Long) = new MacAddress((this.value - value) & maxValue)
}
object MacAddress {
val N_BYTES = 6
// def apply(string: String): MacAddress = new MacAddress(SmallByteArray.parseAsLong(string, N_BYTES))
// def unapply(macAddress: MacAddress): Some[String] = macAddress.toString
}
package be.jvb.iptypes
/**
* Enumeration of possible radix values (hexadecimal and decimal).
*
* @author <a href="http://janvanbesien.blogspot.com">Jan Van Besien</a>
*/
private[iptypes] sealed trait Radix {
val radix:Int
}
private[iptypes] final case class HEX() extends Radix {
override val radix = 16
}
private[iptypes] final case class DEC() extends Radix {
override val radix = 10
}
\ No newline at end of file
package be.jvb.iptypes
import java.util.Arrays
import scala.math.Ordered
import java.util
/**
* Represents a byte array which is small enough to fit in a long (max 8 bytes).
*
* @author <a href="http://janvanbesien.blogspot.com">Jan Van Besien</a>
*/
private[iptypes] trait SmallByteArray extends Ordered[SmallByteArray] {
val value: Long
/** How many bytes do we use (max 8). */
protected def nBytes: Int
/** In what radix do we represent the bytes when converting to a string. */
protected def radix: Radix
/** Do we need to padd the bytes with zeros when converting to a string. */
protected def zeroPaddingUpTo: Int = 0
val maxValue = Math.pow(2, nBytes * 8).toLong - 1
if (nBytes < 0 || nBytes > 8) {
throw new IllegalArgumentException("SmallByteArray can be used for arrays of length 0 to 8 only")
}
if (value > maxValue || value < 0) {
throw new IllegalArgumentException("out of range [0x" + java.lang.Long.toHexString(value) + "] with [" + nBytes + "] bytes")
}
/**
* @return integer array of the bytes in this byte array.
*/
def toIntArray: Array[Int] = {
val ints = new Array[Int](nBytes)
for (i <- 0 until nBytes) {
ints(i) = (((value << i * 8) >>> 8 * (nBytes - 1)) & 0xFF).asInstanceOf[Int]
}
ints.foreach((anInt) => assert(anInt >= 0 && anInt <= 255))
ints
}
/**
* @return byte array of the bytes in this byte array.
*/
def toByteArray: Array[Byte] = {
val bytes = new Array[Byte](nBytes)
for (i <- 0 until nBytes) {
bytes(i) = (((value << i * 8) >>> 8 * (nBytes - 1)) & 0xFF).asInstanceOf[Byte]
}
bytes
}
override def compare(that: SmallByteArray): Int = {
this.value.compare(that.value)
}
// equals implemented as suggested in staircase book
override def equals(other: Any): Boolean = {
other match {
case that: SmallByteArray => that.canEqual(this) && this.value == that.value
case _ => false
}
}
protected def canEqual(other: Any): Boolean = {
other.isInstanceOf[SmallByteArray]
}
override def hashCode = {
value.hashCode
}
/**
* @return String representation of the byte array, with "." between every byte.
*/
override def toString: String = {
val ints = toIntArray
val strings = for (i <- 0 until nBytes) yield String.format(formatString, ints(i).asInstanceOf[Object])
strings.mkString(".")
}
private lazy val formatString = {
radix match {
case HEX() => {
if (zeroPaddingUpTo != 0)
"%0" + zeroPaddingUpTo + "X"
else
"%X"
}
case DEC() => {
if (zeroPaddingUpTo != 0)
"%0" + zeroPaddingUpTo + "d"
else
"%d"
}
}
}
}
object SmallByteArray {
private[iptypes] def parseAsLong(string: String, length: Int, radix: Radix): Long = {
if (string eq null)
throw new IllegalArgumentException("can not parse [null]")
val longArray = parseAsLongArray(string, radix)
validate(longArray, length)
mergeBytesOfArrayIntoLong(longArray)
}
private def parseAsLongArray(string: String, radix: Radix): Array[Long] = {
string.split("\\.").map(java.lang.Long.parseLong(_, radix.radix))
}
private def validate(array: Array[Long], length: Int) = {
if (array.length != length)
throw new IllegalArgumentException("can not parse values [" + util.Arrays.toString(array) + "] into a SmallByteArray of [" + length + "] bytes")
if (!array.filter(_ < 0).isEmpty)
throw new IllegalArgumentException("each element should be positive [" + util.Arrays.toString(array) + "]")
if (!array.filter(_ > 255).isEmpty)
throw new IllegalArgumentException("each element should be less than 255 [" + util.Arrays.toString(array) + "]")
}
private def mergeBytesOfArrayIntoLong(array: Array[Long]): Long = {
var result = 0L
for (i <- 0 until array.length) {
result |= (array(i) << ((array.length - i - 1) * 8))
}
result
}
}
......@@ -53,6 +53,7 @@ import org.apache.http.conn.util.InetAddressUtils
import android.os.Message
import scala.Some
import scala.concurrent.ops._
import be.jvb.iptypes.{IpNetwork, IpAddress}
object ShadowVpnService {
def isServiceStarted(context: Context): Boolean = {
......@@ -236,10 +237,15 @@ class ShadowVpnService extends VpnService {
def startVpn() {
val address = config.proxy.split('.')
val prefix1 = address(0)
val prefix2 = address.slice(0, 2).mkString(".")
val prefix3 = address.slice(0, 3).mkString(".")
val proxy_address = new IpAddress(config.proxy)
val private_networks = Array[IpNetwork](
new IpNetwork("127.0.0.0/8"),
new IpNetwork("10.0.0.0/8"),
new IpNetwork("172.16.0.0/12"),
new IpNetwork("192.168.0.0/16")
)
val builder = new Builder()
builder
......@@ -252,30 +258,32 @@ class ShadowVpnService extends VpnService {
builder.addRoute("0.0.0.0", 0)
} else if (config.isGFWList) {
val gfwList = getResources.getStringArray(R.array.gfw_list)
gfwList.foreach(addr =>
if (addr != prefix2) {
builder.addRoute(addr + ".0.0", 16)
} else {
for (i <- 0 to 255) {
val prefix = Array(addr, i.toString).mkString(".")
if (prefix != prefix3) builder.addRoute(prefix + ".0", 24)
}
})
gfwList.foreach(addr => {
val network = new IpNetwork(addr)
if (!network.contains(proxy_address)) {
builder.addRoute(network.address.toString, network.mask.prefixLength)
Log.d(Shadowsocks.TAG, "add route: " + addr)
}
})
} else {
for (i <- 1 to 254) {
if (i != 127 && i != 172 && i != 192 && i != 10 && i.toString != prefix1) {
builder.addRoute(i + ".0.0.0", 8)
} else if (i.toString == prefix1) {
val network = new IpNetwork(i.toString + ".0.0.0/8")
if (!network.contains(proxy_address) &&
private_networks.forall(range => !network.contains(range))) {
builder.addRoute(i + ".0.0.0", 8)
} else {
for (j <- 0 to 255) {
val prefix = Array(i.toString, j.toString).mkString(".")
if (prefix != prefix2) builder.addRoute(prefix + ".0.0", 16)
val subNetwork = new IpNetwork(i.toString + "." + j.toString + ".0.0/16")
if (!subNetwork.contains(proxy_address) &&
private_networks.forall(range => !range.overlaps(subNetwork))) {
builder.addRoute(subNetwork.address.toString, subNetwork.mask.prefixLength)
}
}
}
}
}
builder.addRoute("8.8.0.0", 16)
builder.addRoute("208.67.0.0", 16)
try {
conn = builder.establish()
......
......@@ -792,5 +792,6 @@ object Utils {
}
}
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment