import Foundation /// A curated CIDR → owner table, used as a fallback when a host has no PTR /// record. Many large operators (Apple's 17.0.0.0/8 famously, Telegram, the /// cloud edges) publish no reverse DNS, so this recovers the obvious ones. /// IPv4 only — the no-PTR giants we care about are reachable on v4. public enum IPRanges { private struct Block { let net: UInt32; let mask: UInt32; let key: String; let name: String } private static let blocks: [Block] = [ ("17.0.0.0/8", "apple", "Apple"), ("149.154.160.0/20", "telegram", "Telegram"), ("91.108.0.0/16", "telegram", "Telegram"), ("13.64.0.0/11", "microsoft", "Microsoft"), // Microsoft 365 / OneDrive front-ends — no PTR, so without these each // IP fragments into its own district. These are Microsoft-operated // service ranges (not generic Azure tenant space, which would wrongly // relabel third-party apps hosted on Azure). ("13.104.0.0/14", "microsoft", "Microsoft"), // incl. 13.107.x ("150.171.0.0/16", "microsoft", "Microsoft"), ("52.108.0.0/14", "microsoft", "Microsoft"), // O365 common ("52.112.0.0/14", "microsoft", "Microsoft"), // Teams/Skype ("40.96.0.0/13", "microsoft", "Microsoft"), // Exchange Online ("40.104.0.0/15", "microsoft", "Microsoft"), ("157.240.0.0/16", "meta", "Meta"), ("31.13.24.0/21", "meta", "Meta"), ("129.134.0.0/16", "meta", "Meta"), ("1.1.1.0/24", "cloudflare", "Cloudflare"), ("104.16.0.0/13", "cloudflare", "Cloudflare"), // Private / link-local space collapses into one neighbourhood. ("10.0.0.0/8", "lan", "Local Network"), ("172.16.0.0/12", "lan", "Local Network"), ("192.168.0.0/16", "lan", "Local Network"), ("169.254.0.0/16", "lan", "Local Network"), ].compactMap { parse($0.0, key: $0.1, name: $0.2) } public static func match(_ ip: String) -> (key: String, name: String)? { guard let value = ipv4ToUInt32(ip) else { return nil } for b in blocks where (value & b.mask) == b.net { return (b.key, b.name) } return nil } // MARK: - Parsing private static func parse(_ cidr: String, key: String, name: String) -> Block? { let parts = cidr.split(separator: "/") guard parts.count == 2, let bits = UInt32(parts[1]), bits <= 32, let net = ipv4ToUInt32(String(parts[0])) else { return nil } let mask: UInt32 = bits == 0 ? 0 : ~UInt32(0) << (32 - bits) return Block(net: net & mask, mask: mask, key: key, name: name) } static func ipv4ToUInt32(_ ip: String) -> UInt32? { let octets = ip.split(separator: ".") guard octets.count == 4 else { return nil } var result: UInt32 = 0 for octet in octets { guard let n = UInt32(octet), n <= 255 else { return nil } result = (result << 8) | n } return result } }