// // DNSConfiguration.swift // ClashX import Cocoa import SystemConfiguration // https://github.com/ivanstegic/menu-bar-dns/blob/main/Menu%20Bar%20DNS/Menu%20Bar%20DNS/DNSConfiguration.swift class DNSConfiguration: NSObject { static let DNSConfigurationTypeKey = Bundle.main.bundleIdentifier! + ".dns" static let ServiceTypeWiFi = "IEEE80211" static let ServiceTypeEthernet = "Ethernet" static func getnterfaceTypeByServiceIDs(_ services: Array) throws -> Dictionary { let allServicesIDsAndInterfaceType = try services.map { service -> (String, String) in guard let id = SCNetworkServiceGetServiceID(service) as String?, let interface = SCNetworkServiceGetInterface(service), let interfaceType = SCNetworkInterfaceGetInterfaceType(interface) as String? else { throw SCCopyLastError() } return (id, interfaceType) } return Dictionary(uniqueKeysWithValues: allServicesIDsAndInterfaceType) } static func isConnectedService(_ service : SCNetworkService) throws -> Bool { guard let id = SCNetworkServiceGetServiceID(service) as String? else { throw SCCopyLastError() } let dynmaicStore = SCDynamicStoreCreate(kCFAllocatorSystemDefault, "DNSSETTING" as CFString, nil, nil) let serviceStateIPv4Key = "State:/Network/Service/\(id)/IPv4" as CFString let value = SCDynamicStoreCopyValue(dynmaicStore, serviceStateIPv4Key) as CFPropertyList? return value != nil } static func getDNSForServiceID(_ serviceID:String) -> [String] { let serviceDNSKey = "State:/Network/Service/\(serviceID)/DNS" as CFString let serviceSetupDNSKey = "Setup:/Network/Service/\(serviceID)/DNS" as CFString let dynmaicStore = SCDynamicStoreCreate(kCFAllocatorSystemDefault, "DNSSETTING" as CFString, nil, nil) var allDNSIPAddresses : Array = [] let dynamicPlist = SCDynamicStoreCopyValue(dynmaicStore, serviceDNSKey) let manualAddressPlist = SCDynamicStoreCopyValue(dynmaicStore, serviceSetupDNSKey) if let dnsValues = manualAddressPlist?[kSCPropNetDNSServerAddresses] as? [String] { allDNSIPAddresses += dnsValues } /* if let dhcpValues = dynamicPlist?[kSCPropNetDNSServerAddresses] as? [String] { let uniqueValues = Array(Set(dhcpValues)) for dhcpValue in uniqueValues { let newvalue = dhcpValue.appending(" (via DHCP)") allDNSIPAddresses.append(newvalue) } } */ return allDNSIPAddresses } static func getAddresses() -> (Array, Array) { var ethernetDNSAddresses : Array = [] var WiFiDNSAddresses : Array = [] do { let prefs = SCPreferencesCreate( nil, DNSConfigurationTypeKey as NSString, nil ) as SCPreferences? let allServicesCF = SCNetworkServiceCopyAll(prefs!) let allServices = allServicesCF as? [SCNetworkService] let allConnectedServices = try allServices?.filter({ (service) -> Bool in return try isConnectedService(service) }) let serviceTypeByIDs = try getnterfaceTypeByServiceIDs(allConnectedServices!) as Dictionary? for (id, type) in serviceTypeByIDs! { switch (type) { case ServiceTypeWiFi: WiFiDNSAddresses += getDNSForServiceID(id) case ServiceTypeEthernet: ethernetDNSAddresses += getDNSForServiceID(id) default: print("") } } } catch { return ([], []) } return (ethernetDNSAddresses, WiFiDNSAddresses) } }