@@ -2,10 +2,14 @@ package io.nekohasekai.sfa.bg
22
33import android.annotation.SuppressLint
44import android.content.pm.PackageManager
5+ import android.net.NetworkCapabilities
56import android.os.Build
67import android.os.Process
8+ import android.system.OsConstants
9+ import android.util.Log
710import androidx.annotation.RequiresApi
811import io.nekohasekai.libbox.InterfaceUpdateListener
12+ import io.nekohasekai.libbox.Libbox
913import io.nekohasekai.libbox.NetworkInterfaceIterator
1014import io.nekohasekai.libbox.PlatformInterface
1115import io.nekohasekai.libbox.StringIterator
@@ -16,7 +20,6 @@ import java.net.Inet6Address
1620import java.net.InetSocketAddress
1721import java.net.InterfaceAddress
1822import java.net.NetworkInterface
19- import java.util.Enumeration
2023import io.nekohasekai.libbox.NetworkInterface as LibboxNetworkInterface
2124
2225interface PlatformInterfaceWrapper : PlatformInterface {
@@ -44,13 +47,19 @@ interface PlatformInterfaceWrapper : PlatformInterface {
4447 destinationAddress : String ,
4548 destinationPort : Int
4649 ): Int {
47- val uid = Application .connectivity.getConnectionOwnerUid(
48- ipProtocol,
49- InetSocketAddress (sourceAddress, sourcePort),
50- InetSocketAddress (destinationAddress, destinationPort)
51- )
52- if (uid == Process .INVALID_UID ) error(" android: connection owner not found" )
53- return uid
50+ try {
51+ val uid = Application .connectivity.getConnectionOwnerUid(
52+ ipProtocol,
53+ InetSocketAddress (sourceAddress, sourcePort),
54+ InetSocketAddress (destinationAddress, destinationPort)
55+ )
56+ if (uid == Process .INVALID_UID ) error(" android: connection owner not found" )
57+ return uid
58+ } catch (e: Exception ) {
59+ Log .e(" PlatformInterface" , " getConnectionOwnerUid" , e)
60+ e.printStackTrace(System .err)
61+ throw e
62+ }
5463 }
5564
5665 override fun packageNameByUid (uid : Int ): String {
@@ -76,10 +85,6 @@ interface PlatformInterfaceWrapper : PlatformInterface {
7685 }
7786 }
7887
79- override fun usePlatformDefaultInterfaceMonitor (): Boolean {
80- return true
81- }
82-
8388 override fun startDefaultInterfaceMonitor (listener : InterfaceUpdateListener ) {
8489 DefaultNetworkMonitor .setListener(listener)
8590 }
@@ -88,12 +93,56 @@ interface PlatformInterfaceWrapper : PlatformInterface {
8893 DefaultNetworkMonitor .setListener(null )
8994 }
9095
91- override fun usePlatformInterfaceGetter (): Boolean {
92- return Build .VERSION .SDK_INT >= Build .VERSION_CODES .R
93- }
94-
9596 override fun getInterfaces (): NetworkInterfaceIterator {
96- return InterfaceArray (NetworkInterface .getNetworkInterfaces())
97+ val networks = Application .connectivity.allNetworks
98+ val networkInterfaces = NetworkInterface .getNetworkInterfaces().toList()
99+ val interfaces = mutableListOf<LibboxNetworkInterface >()
100+ for (network in networks) {
101+ val boxInterface = LibboxNetworkInterface ()
102+ val linkProperties = Application .connectivity.getLinkProperties(network) ? : continue
103+ val networkCapabilities =
104+ Application .connectivity.getNetworkCapabilities(network) ? : continue
105+ boxInterface.name = linkProperties.interfaceName
106+ val networkInterface =
107+ networkInterfaces.find { it.name == boxInterface.name } ? : continue
108+ boxInterface.dnsServer =
109+ StringArray (linkProperties.dnsServers.mapNotNull { it.hostAddress }.iterator())
110+ boxInterface.type = when {
111+ networkCapabilities.hasTransport(NetworkCapabilities .TRANSPORT_WIFI ) -> Libbox .InterfaceTypeWIFI
112+ networkCapabilities.hasTransport(NetworkCapabilities .TRANSPORT_CELLULAR ) -> Libbox .InterfaceTypeCellular
113+ networkCapabilities.hasTransport(NetworkCapabilities .TRANSPORT_ETHERNET ) -> Libbox .InterfaceTypeEthernet
114+ else -> Libbox .InterfaceTypeOther
115+ }
116+ boxInterface.index = networkInterface.index
117+ runCatching {
118+ boxInterface.mtu = networkInterface.mtu
119+ }.onFailure {
120+ Log .e(
121+ " PlatformInterface" , " failed to get mtu for interface ${boxInterface.name} " , it
122+ )
123+ }
124+ boxInterface.addresses =
125+ StringArray (networkInterface.interfaceAddresses.mapTo(mutableListOf ()) { it.toPrefix() }
126+ .iterator())
127+ var dumpFlags = 0
128+ if (networkCapabilities.hasCapability(NetworkCapabilities .NET_CAPABILITY_INTERNET )) {
129+ dumpFlags = OsConstants .IFF_UP or OsConstants .IFF_RUNNING
130+ }
131+ if (networkInterface.isLoopback) {
132+ dumpFlags = dumpFlags or OsConstants .IFF_LOOPBACK
133+ }
134+ if (networkInterface.isPointToPoint) {
135+ dumpFlags = dumpFlags or OsConstants .IFF_POINTOPOINT
136+ }
137+ if (networkInterface.supportsMulticast()) {
138+ dumpFlags = dumpFlags or OsConstants .IFF_MULTICAST
139+ }
140+ boxInterface.flags = dumpFlags
141+ boxInterface.metered =
142+ ! networkCapabilities.hasCapability(NetworkCapabilities .NET_CAPABILITY_NOT_METERED )
143+ interfaces.add(boxInterface)
144+ }
145+ return InterfaceArray (interfaces.iterator())
97146 }
98147
99148 override fun underNetworkExtension (): Boolean {
@@ -108,55 +157,29 @@ interface PlatformInterfaceWrapper : PlatformInterface {
108157 }
109158
110159 override fun readWIFIState (): WIFIState ? {
111- @Suppress(" DEPRECATION" )
112- val wifiInfo = Application .wifiManager.connectionInfo ? : return null
160+ @Suppress(" DEPRECATION" ) val wifiInfo =
161+ Application .wifiManager.connectionInfo ? : return null
113162 var ssid = wifiInfo.ssid
163+ if (ssid == " <unknown ssid>" ) {
164+ return WIFIState (" " , " " )
165+ }
114166 if (ssid.startsWith(" \" " ) && ssid.endsWith(" \" " )) {
115167 ssid = ssid.substring(1 , ssid.length - 1 )
116168 }
117169 return WIFIState (ssid, wifiInfo.bssid)
118170 }
119171
120- private class InterfaceArray (private val iterator : Enumeration < NetworkInterface >) :
172+ private class InterfaceArray (private val iterator : Iterator < LibboxNetworkInterface >) :
121173 NetworkInterfaceIterator {
122174
123175 override fun hasNext (): Boolean {
124- return iterator.hasMoreElements ()
176+ return iterator.hasNext ()
125177 }
126178
127179 override fun next (): LibboxNetworkInterface {
128- val element = iterator.nextElement()
129- return LibboxNetworkInterface ().apply {
130- name = element.name
131- index = element.index
132- runCatching {
133- mtu = element.mtu
134- }
135- addresses =
136- StringArray (
137- element.interfaceAddresses.mapTo(mutableListOf ()) { it.toPrefix() }
138- .iterator()
139- )
140- runCatching {
141- flags = element.flags
142- }
143- }
144- }
145-
146- private fun InterfaceAddress.toPrefix (): String {
147- return if (address is Inet6Address ) {
148- " ${Inet6Address .getByAddress(address.address).hostAddress} /${networkPrefixLength} "
149- } else {
150- " ${address.hostAddress} /${networkPrefixLength} "
151- }
180+ return iterator.next()
152181 }
153182
154- private val NetworkInterface .flags: Int
155- @SuppressLint(" SoonBlockedPrivateApi" )
156- get() {
157- val getFlagsMethod = NetworkInterface ::class .java.getDeclaredMethod(" getFlags" )
158- return getFlagsMethod.invoke(this ) as Int
159- }
160183 }
161184
162185 private class StringArray (private val iterator : Iterator <String >) : StringIterator {
@@ -175,4 +198,17 @@ interface PlatformInterfaceWrapper : PlatformInterface {
175198 }
176199 }
177200
201+ private fun InterfaceAddress.toPrefix (): String {
202+ return if (address is Inet6Address ) {
203+ " ${Inet6Address .getByAddress(address.address).hostAddress} /${networkPrefixLength} "
204+ } else {
205+ " ${address.hostAddress} /${networkPrefixLength} "
206+ }
207+ }
208+
209+ private val NetworkInterface .flags: Int
210+ @SuppressLint(" SoonBlockedPrivateApi" ) get() {
211+ val getFlagsMethod = NetworkInterface ::class .java.getDeclaredMethod(" getFlags" )
212+ return getFlagsMethod.invoke(this ) as Int
213+ }
178214}
0 commit comments