From e82ba20c20b88c95989a8662b887d73252e74590 Mon Sep 17 00:00:00 2001 From: Mygod Date: Fri, 5 Jan 2018 09:10:04 +0800 Subject: [PATCH] Simplify IP rules for Wi-Fi direct mode --- .../be/mygod/vpnhotspot/HotspotService.kt | 5 ++- .../java/be/mygod/vpnhotspot/MainActivity.kt | 2 +- .../main/java/be/mygod/vpnhotspot/Routing.kt | 38 ++++++------------- 3 files changed, 15 insertions(+), 30 deletions(-) diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/HotspotService.kt b/mobile/src/main/java/be/mygod/vpnhotspot/HotspotService.kt index d90cfca8..1a703450 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/HotspotService.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/HotspotService.kt @@ -169,7 +169,7 @@ class HotspotService : Service(), WifiP2pManager.ChannelListener { } catch (_: Routing.InterfaceNotFoundException) { startFailure(getString(R.string.exception_interface_not_found)) return START_NOT_STICKY - }.apRule().forward().dnsRedirect(dns) + }.rule().forward().dnsRedirect(dns) if (routing.start()) { this.routing = routing apConfiguration = NetUtils.loadApConfiguration() @@ -229,7 +229,8 @@ class HotspotService : Service(), WifiP2pManager.ChannelListener { } catch (_: Routing.InterfaceNotFoundException) { startFailure(getString(R.string.exception_interface_not_found), group) return - }.p2pRule().forward().dnsRedirect(dns) + }.ipForward() // Wi-Fi direct doesn't enable ip_forward + .rule().forward().dnsRedirect(dns) if (routing.start()) { this.routing = routing doStart(group) diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/MainActivity.kt b/mobile/src/main/java/be/mygod/vpnhotspot/MainActivity.kt index d9212c78..d36a0a07 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/MainActivity.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/MainActivity.kt @@ -87,7 +87,7 @@ class MainActivity : AppCompatActivity(), ServiceConnection, Toolbar.OnMenuItemC } holder.binding.device = device holder.binding.ipAddress = when (position) { - 0 -> binder?.service?.routing?.hostAddress?.address?.hostAddress + 0 -> binder?.service?.routing?.hostAddress else -> arpCache[device?.deviceAddress] } holder.binding.executePendingBindings() diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/Routing.kt b/mobile/src/main/java/be/mygod/vpnhotspot/Routing.kt index 29f90f68..ae47be3d 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/Routing.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/Routing.kt @@ -13,43 +13,28 @@ class Routing(private val upstream: String, val downstream: String, ownerAddress "while iptables -D FORWARD -j vpnhotspot_fwd; do done", "iptables -F vpnhotspot_fwd", "iptables -X vpnhotspot_fwd", - "while ip rule del lookup 62; do done", - "ip route flush table 62", "while ip rule del priority 17999; do done") } class InterfaceNotFoundException : IOException() - val hostAddress = NetworkInterface.getByName(downstream)?.interfaceAddresses - ?.singleOrNull { if (ownerAddress == null) it.address is Inet4Address else it.address == ownerAddress } - ?: throw InterfaceNotFoundException() + val hostAddress: String = (ownerAddress ?: NetworkInterface.getByName(downstream)?.inetAddresses?.asSequence() + ?.singleOrNull { it is Inet4Address } ?: throw InterfaceNotFoundException()).hostAddress private val startScript = LinkedList() private val stopScript = LinkedList() - fun p2pRule(): Routing { - val address = hostAddress.address.address - val subnetPrefixLength = hostAddress.networkPrefixLength - // clear suffix bits - var done = subnetPrefixLength.toInt() - while (done < address.size shl 3) { - val index = done shr 3 - address[index] = (address[index].toInt() and (0x7f00 shr (done and 7))).toByte() - done = (index + 1) shl 3 - } - startScript.add("echo 1 >/proc/sys/net/ipv4/ip_forward") // Wi-Fi direct doesn't enable ip_forward - startScript.add("ip route add default dev $upstream scope link table 62") - startScript.add("ip route add ${InetAddress.getByAddress(address).hostAddress}/$subnetPrefixLength dev $downstream scope link table 62") - startScript.add("ip route add broadcast 255.255.255.255 dev $downstream scope link table 62") - startScript.add("ip rule add iif $downstream lookup 62") - // removing each rule may fail if downstream is already removed - stopScript.addFirst("ip route flush table 62") - stopScript.addFirst("ip rule del iif $downstream lookup 62") + fun ipForward(): Routing { + startScript.add("echo 1 >/proc/sys/net/ipv4/ip_forward") return this } - /* Since Android 5.0, RULE_PRIORITY_TETHERING = 18000. - * https://android.googlesource.com/platform/system/netd/+/b9baf26/server/RouteController.cpp#65 */ - fun apRule(): Routing { + /** + * Since Android 5.0, RULE_PRIORITY_TETHERING = 18000. + * This also works for Wi-Fi direct where there's no rule at 18000. + * + * Source: https://android.googlesource.com/platform/system/netd/+/b9baf26/server/RouteController.cpp#65 + */ + fun rule(): Routing { startScript.add("ip rule add from all iif $downstream lookup $upstream priority 17999") stopScript.addFirst("ip rule del from all iif $downstream lookup $upstream priority 17999") return this @@ -67,7 +52,6 @@ class Routing(private val upstream: String, val downstream: String, ownerAddress } fun dnsRedirect(dns: String): Routing { - val hostAddress = hostAddress.address.hostAddress startScript.add("iptables -t nat -A PREROUTING -i $downstream -p tcp -d $hostAddress --dport 53 -j DNAT --to-destination $dns") startScript.add("iptables -t nat -A PREROUTING -i $downstream -p udp -d $hostAddress --dport 53 -j DNAT --to-destination $dns") stopScript.addFirst("iptables -t nat -D PREROUTING -i $downstream -p tcp -d $hostAddress --dport 53 -j DNAT --to-destination $dns")