IfManager: added String representation for readability

This commit is contained in:
mahee96
2026-02-28 06:45:12 +05:30
parent 3b9b45a06f
commit 95953ca0e9

View File

@@ -30,72 +30,97 @@ fileprivate func socktouint(_ sock: inout sockaddr) -> UInt32 {
return addr.s_addr.bigEndian return addr.s_addr.bigEndian
} }
struct NetInfo: Hashable { struct NetInfo: Hashable, CustomStringConvertible {
let name: String let name: String
let host: UInt32
let mask: UInt32 let hostIP: String
let maskIP: String
private let host: UInt32
private let mask: UInt32
init(name: String, host: UInt32, mask: UInt32) { init(name: String, host: UInt32, mask: UInt32) {
self.name = name self.name = name
self.host = host self.host = host
self.mask = mask self.mask = mask
self.hostIP = uti(host) ?? "nil"
self.maskIP = uti(mask) ?? "nil"
} }
init?(_ ifaddr: ifaddrs) { init?(_ ifaddr: ifaddrs) {
guard let ianame = String(utf8String: ifaddr.ifa_name) else { return nil } guard
self = .init(name: ianame, host: socktouint(&ifaddr.ifa_addr.pointee), mask: socktouint(&ifaddr.ifa_netmask.pointee)) let ianame = String(utf8String: ifaddr.ifa_name)
else { return nil }
let host = socktouint(&ifaddr.ifa_addr.pointee)
let mask = socktouint(&ifaddr.ifa_netmask.pointee)
self.init(name: ianame, host: host, mask: mask)
} }
var minIP: UInt32 { host & mask } // computed networking values (still numeric internally)
var maxIP: UInt32 { host | ~mask } var minIPInSubnet: UInt32 { host & mask }
var hostIP: String { uti(host) ?? "nil" } var maxIPInSubnet: UInt32 { host | ~mask }
var maskIP: String { uti(mask) ?? "nil" }
var minIPString: String { uti(minIPInSubnet) ?? "nil" }
var maxIPString: String { uti(maxIPInSubnet) ?? "nil" }
var description: String {
"\(name) | ip=\(hostIP) mask=\(maskIP) range=\(minIPString)-\(maxIPString)"
}
} }
final class IfManager: Sendable { final class IfManager: @unchecked Sendable {
private init() {}
static let shared = IfManager() static let shared = IfManager()
nonisolated(unsafe) private(set) var addrs: Set<NetInfo> = Set()
init() { // always get freshly computed addresses
self.addrs = IfManager.update() var addrs: Set<NetInfo> {
Self.query()
} }
public func update() { private static func query() -> Set<NetInfo> {
addrs = IfManager.update()
}
private static func update() -> Set<NetInfo> {
var addrs = Set<NetInfo>() var addrs = Set<NetInfo>()
var head: UnsafeMutablePointer<ifaddrs>? = nil var head: UnsafeMutablePointer<ifaddrs>? = nil
guard getifaddrs(&head) == 0, let first = head else { return addrs } guard getifaddrs(&head) == 0, let first = head else { return addrs }
defer { freeifaddrs(head) } defer { freeifaddrs(head) }
var ifaddr: UnsafeMutablePointer<ifaddrs>? = first
while let next = ifaddr { var cursor: UnsafeMutablePointer<ifaddrs>? = first
while let current = cursor {
// we only want v4 interfaces that aren't loopback and aren't masked 255.255.255.255 // we only want v4 interfaces that aren't loopback and aren't masked 255.255.255.255
if (next.pointee.ifa_addr.pointee.sa_family == UInt8(AF_INET)), let entry = current.pointee
(Int32(next.pointee.ifa_flags) & (IFF_UP|IFF_RUNNING|IFF_LOOPBACK)) == (IFF_UP|IFF_RUNNING), let flags = Int32(entry.ifa_flags)
let info = NetInfo(next.pointee),
info.mask != 0xffffffff { let isIPv4 = entry.ifa_addr.pointee.sa_family == UInt8(AF_INET)
let isActive = (flags & (IFF_UP | IFF_RUNNING | IFF_LOOPBACK)) == (IFF_UP | IFF_RUNNING)
if isIPv4, isActive, let info = NetInfo(entry), info.maskIP != "255.255.255.255" {
addrs.insert(info) addrs.insert(info)
} }
ifaddr = next.pointee.ifa_next
cursor = entry.ifa_next
} }
return addrs return addrs
} }
var nextLAN: NetInfo? { private var nextLAN: NetInfo? {
addrs.first { $0.name.starts(with: "en") } addrs.first { $0.name.starts(with: "en") }
} }
var nextProbableSideVPN: NetInfo? { var nextProbableSideVPN: NetInfo? {
// try old 10.7.0.0 first, then fallback to next v4 // try old 10.7.0.1 first, then fallback to next v4
// user should only be connected to StosVPN/LocalDevVPN // user should only be connected to StosVPN/LocalDevVPN
addrs.first { $0.host == 168230912 || $0.name.starts(with: "utun") } addrs.first {
$0.minIPString == "10.7.0.1" ||
$0.minIPString == "192.168.56.1" ||
$0.name.starts(with: "utun")
}
} }
var sideVPNPatched: Bool { var sideVPNPatched: Bool {
nextLAN?.mask == nextProbableSideVPN?.mask && nextLAN?.maskIP == nextProbableSideVPN?.maskIP &&
nextLAN?.maxIP == nextProbableSideVPN?.maxIP nextLAN?.maxIPInSubnet == nextProbableSideVPN?.maxIPInSubnet
} }
} }