// // Util.swift // Tun // // Created by 安礼成 on 2024/1/19. // import Foundation import SystemConfiguration import Network import Darwin struct SDLUtil { public static func int32ToIp(_ num: UInt32) -> String { let ip0 = (UInt8) (num >> 24 & 0xFF) let ip1 = (UInt8) (num >> 16 & 0xFF) let ip2 = (UInt8) (num >> 8 & 0xFF) let ip3 = (UInt8) (num & 0xFF) return "\(ip0).\(ip1).\(ip2).\(ip3)" } public static func netMaskIp(maskLen: UInt8) -> String { let len0 = 32 - maskLen let num: UInt32 = (0xFFFFFFFF >> len0) << len0 let ip0 = (UInt8) (num >> 24 & 0xFF) let ip1 = (UInt8) (num >> 16 & 0xFF) let ip2 = (UInt8) (num >> 8 & 0xFF) let ip3 = (UInt8) (num & 0xFF) return "\(ip0).\(ip1).\(ip2).\(ip3)" } public static func ipv4StrToInt32(_ ip: String) -> UInt32? { let parts = ip.split(separator: ".") guard parts.count == 4 else { return nil } var result: UInt32 = 0 for part in parts { guard let byte = UInt8(part) else { return nil } result = (result << 8) | UInt32(byte) } return result } public static func ipv6DataToString(_ data: Data) -> String? { guard data.count == 16 else { return nil } return data.withUnsafeBytes { rawBuffer in guard let baseAddress = rawBuffer.baseAddress else { return nil } var hostBuffer = [CChar](repeating: 0, count: Int(INET6_ADDRSTRLEN)) guard inet_ntop(AF_INET6, baseAddress, &hostBuffer, socklen_t(INET6_ADDRSTRLEN)) != nil else { return nil } return String(cString: hostBuffer) } } // 判断ip地址是否在同一个网络 public static func inSameNetwork(ip: UInt32, compareIp: UInt32, maskLen: UInt8) -> Bool { if ip == compareIp { return true } let len0 = 32 - maskLen // 掩码值 let mask: UInt32 = (0xFFFFFFFF >> len0) << len0 return ip & mask == compareIp & mask } public static func formatMacAddress(mac: Data) -> String { let bytes = [UInt8](mac) return bytes.map { String(format: "%02X", $0) }.joined(separator: ":").lowercased() } public static func getMacOSSystemDnsServers() -> [String] { var results = [String]() // 获取全局 DNS 配置 if let dict = SCDynamicStoreCopyValue(nil, "State:/Network/Global/DNS" as CFString) as? [String: Any] { if let servers = dict["ServerAddresses"] as? [String] { results = servers } } return results } // 域名解析 static func resolveHostname(host: String) async -> String? { let endpoint = NWEndpoint.hostPort(host: NWEndpoint.Host(host), port: 53) let parameters = NWParameters.udp // 即使还没正式开始,也加上这个,确保不会被残留的旧 utun 路由卡死 parameters.prohibitedInterfaceTypes = [.other] let connection = NWConnection(to: endpoint, using: parameters) return await withCheckedContinuation { continuation in connection.stateUpdateHandler = { state in if case .ready = state { if let path = connection.currentPath, case .hostPort(let resolvedHost, _) = path.remoteEndpoint { let ip = String(describing: resolvedHost) continuation.resume(returning: ip) connection.cancel() } } else if case .failed = state { continuation.resume(returning: nil) } } connection.start(queue: .global()) } } }