Auto detect prefix length as well
Unfortunately NetworkInterface requires INTERNET permission. (this can actually be bypassed very easily but let's prefer usage of public API)
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
|
||||
<application
|
||||
android:name=".App"
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
package be.mygod.vpnhotspot
|
||||
|
||||
import java.io.File
|
||||
|
||||
class ArpCache(downstream: String? = null) : HashMap<String, String>() {
|
||||
companion object {
|
||||
private val spaces = " +".toPattern()
|
||||
private val mac = "^([0-9a-f]{2}:){5}[0-9a-f]{2}$".toPattern()
|
||||
}
|
||||
|
||||
init {
|
||||
File("/proc/net/arp").bufferedReader().useLines {
|
||||
for (line in it) {
|
||||
val parts = line.split(spaces)
|
||||
// IP address HW type Flags HW address Mask Device
|
||||
if (parts.size >= 4 && (downstream == null || parts.getOrNull(5) == downstream) &&
|
||||
mac.matcher(parts[3]).matches()) put(parts[3], parts[0])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ import android.support.v4.content.LocalBroadcastManager
|
||||
import android.util.Log
|
||||
import android.widget.Toast
|
||||
import be.mygod.vpnhotspot.App.Companion.app
|
||||
import java.net.NetworkInterface
|
||||
|
||||
class HotspotService : Service(), WifiP2pManager.ChannelListener {
|
||||
companion object {
|
||||
@@ -63,26 +64,7 @@ class HotspotService : Service(), WifiP2pManager.ChannelListener {
|
||||
val info = intent.getParcelableExtra<WifiP2pInfo>(WifiP2pManager.EXTRA_WIFI_P2P_INFO)
|
||||
val net = intent.getParcelableExtra<NetworkInfo>(WifiP2pManager.EXTRA_NETWORK_INFO)
|
||||
val group = intent.getParcelableExtra<WifiP2pGroup>(WifiP2pManager.EXTRA_WIFI_P2P_GROUP)
|
||||
val hostAddress = info.groupOwnerAddress?.hostAddress
|
||||
val downstream = group.`interface`
|
||||
if (info.groupFormed && info.isGroupOwner &&
|
||||
downstream != null && hostAddress != null && this.downstream == null) {
|
||||
this.downstream = downstream
|
||||
this.hostAddress = hostAddress
|
||||
if (noisySu("echo 1 >/proc/sys/net/ipv4/ip_forward",
|
||||
"ip route add default dev $upstream scope link table 62",
|
||||
"ip route add $hostAddress/$subnetPrefixLength dev $downstream scope link table 62",
|
||||
"ip route add broadcast 255.255.255.255 dev $downstream scope link table 62",
|
||||
"ip rule add from $hostAddress/$subnetPrefixLength lookup 62",
|
||||
"iptables -N vpnhotspot_fwd",
|
||||
"iptables -A vpnhotspot_fwd -i $upstream -o $downstream -m state --state ESTABLISHED,RELATED -j ACCEPT",
|
||||
"iptables -A vpnhotspot_fwd -i $downstream -o $upstream -j ACCEPT",
|
||||
"iptables -I FORWARD -j vpnhotspot_fwd",
|
||||
"iptables -t nat -A PREROUTING -i $downstream -p tcp -d $hostAddress --dport 53 -j DNAT --to-destination $dns",
|
||||
"iptables -t nat -A PREROUTING -i $downstream -p udp -d $hostAddress --dport 53 -j DNAT --to-destination $dns")) {
|
||||
doStart(group)
|
||||
} else startFailure("Something went wrong, please check logcat.")
|
||||
}
|
||||
if (downstream == null) onGroupCreated(info, group)
|
||||
this@HotspotService.group = group
|
||||
binder.data?.onGroupChanged()
|
||||
showNotification(group)
|
||||
@@ -99,7 +81,7 @@ class HotspotService : Service(), WifiP2pManager.ChannelListener {
|
||||
* https://android.googlesource.com/platform/frameworks/base/+/android-4.0.1_r1/wifi/java/android/net/wifi/p2p/WifiP2pService.java#1028
|
||||
* https://android.googlesource.com/platform/frameworks/opt/net/wifi/+/a8d5e40/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java#2547
|
||||
*/
|
||||
private val subnetPrefixLength get() = app.pref.getString("service.subnetPrefixLength", "24")
|
||||
private var subnetPrefixLength: Short = 24
|
||||
private val dns get() = app.pref.getString("service.dns", "8.8.8.8:53")
|
||||
|
||||
var status = Status.IDLE
|
||||
@@ -183,6 +165,35 @@ class HotspotService : Service(), WifiP2pManager.ChannelListener {
|
||||
Intent(this, MainActivity::class.java), PendingIntent.FLAG_UPDATE_CURRENT))
|
||||
.build())
|
||||
|
||||
private fun onGroupCreated(info: WifiP2pInfo, group: WifiP2pGroup) {
|
||||
val owner = info.groupOwnerAddress
|
||||
val hostAddress = owner?.hostAddress
|
||||
val downstream = group.`interface`
|
||||
if (!info.groupFormed || !info.isGroupOwner || downstream == null || hostAddress == null) return
|
||||
this.downstream = downstream
|
||||
this.hostAddress = hostAddress
|
||||
var subnetPrefixLength = NetworkInterface.getByName(downstream)?.interfaceAddresses
|
||||
?.singleOrNull { it.address == owner }?.networkPrefixLength
|
||||
if (subnetPrefixLength == null) {
|
||||
Log.w(TAG, "Unable to find prefix length of interface $downstream, 24 is assumed")
|
||||
subnetPrefixLength = 24
|
||||
}
|
||||
this.subnetPrefixLength = subnetPrefixLength
|
||||
if (noisySu("echo 1 >/proc/sys/net/ipv4/ip_forward",
|
||||
"ip route add default dev $upstream scope link table 62",
|
||||
"ip route add $hostAddress/$subnetPrefixLength dev $downstream scope link table 62",
|
||||
"ip route add broadcast 255.255.255.255 dev $downstream scope link table 62",
|
||||
"ip rule add from $hostAddress/$subnetPrefixLength lookup 62",
|
||||
"iptables -N vpnhotspot_fwd",
|
||||
"iptables -A vpnhotspot_fwd -i $upstream -o $downstream -m state --state ESTABLISHED,RELATED -j ACCEPT",
|
||||
"iptables -A vpnhotspot_fwd -i $downstream -o $upstream -j ACCEPT",
|
||||
"iptables -I FORWARD -j vpnhotspot_fwd",
|
||||
"iptables -t nat -A PREROUTING -i $downstream -p tcp -d $hostAddress --dport 53 -j DNAT --to-destination $dns",
|
||||
"iptables -t nat -A PREROUTING -i $downstream -p udp -d $hostAddress --dport 53 -j DNAT --to-destination $dns")) {
|
||||
doStart(group)
|
||||
} else startFailure("Something went wrong, please check logcat.")
|
||||
}
|
||||
|
||||
private fun clean() {
|
||||
if (receiverRegistered) {
|
||||
unregisterReceiver(receiver)
|
||||
|
||||
@@ -66,14 +66,14 @@ class MainActivity : AppCompatActivity(), ServiceConnection, Toolbar.OnMenuItemC
|
||||
inner class ClientAdapter : RecyclerView.Adapter<ClientViewHolder>() {
|
||||
private var owner: WifiP2pDevice? = null
|
||||
private lateinit var clients: MutableCollection<WifiP2pDevice>
|
||||
private lateinit var arpCache: ArpCache
|
||||
private lateinit var arpCache: Map<String, String>
|
||||
|
||||
fun fetchClients() {
|
||||
if (data.running) {
|
||||
val binder = binder!!
|
||||
owner = binder.service.group.owner
|
||||
clients = binder.service.group.clientList
|
||||
arpCache = ArpCache(binder.service.downstream)
|
||||
arpCache = NetUtils.arp(binder.service.downstream)
|
||||
} else owner = null
|
||||
notifyDataSetChanged() // recreate everything
|
||||
}
|
||||
|
||||
17
mobile/src/main/java/be/mygod/vpnhotspot/NetUtils.kt
Normal file
17
mobile/src/main/java/be/mygod/vpnhotspot/NetUtils.kt
Normal file
@@ -0,0 +1,17 @@
|
||||
package be.mygod.vpnhotspot
|
||||
|
||||
import java.io.File
|
||||
|
||||
object NetUtils {
|
||||
private val spaces = " +".toPattern()
|
||||
private val mac = "^([0-9a-f]{2}:){5}[0-9a-f]{2}$".toPattern()
|
||||
|
||||
fun arp(iface: String? = null) = File("/proc/net/arp").bufferedReader().useLines {
|
||||
// IP address HW type Flags HW address Mask Device
|
||||
it.map { it.split(spaces) }
|
||||
.drop(1)
|
||||
.filter { it.size >= 4 && (iface == null || it.getOrNull(5) == iface) &&
|
||||
mac.matcher(it[3]).matches() }
|
||||
.associateBy({ it[3] }, { it[0] })
|
||||
}
|
||||
}
|
||||
@@ -8,13 +8,6 @@
|
||||
android:title="Upstream interface"
|
||||
android:summary="%s"
|
||||
android:defaultValue="tun0"/>
|
||||
<AutoSummaryEditTextPreference
|
||||
android:key="service.subnetPrefixLength"
|
||||
android:title="Subnet prefix length"
|
||||
android:summary="%s"
|
||||
android:inputType="number"
|
||||
android:maxLength="3"
|
||||
android:defaultValue="24"/>
|
||||
<AutoSummaryEditTextPreference
|
||||
android:key="service.dns"
|
||||
android:title="Downstream DNS server:port"
|
||||
|
||||
Reference in New Issue
Block a user