Files
networkcity/Sources/NetworkCityCore/IPRanges.swift
T
timban 34cdcee00b Group Microsoft/OneDrive no-PTR ranges into one district
OneDrive's IPs (e.g. 13.107.x, 150.171.x) have no PTR and weren't in our
CIDR table, so each fragmented into its own IP-named district — a long
session showed dozens, all with the "OneDrive" process subtitle. Add the
documented Microsoft 365 service ranges so they collapse to one Microsoft
district. Deliberately excludes generic Azure tenant space, which would
mislabel third-party apps hosted on Azure.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 10:46:53 -07:00

67 lines
3.1 KiB
Swift

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
}
}