diff --git a/Sources/NetworkCityCore/IPRanges.swift b/Sources/NetworkCityCore/IPRanges.swift index 2347eba..f79fd9d 100644 --- a/Sources/NetworkCityCore/IPRanges.swift +++ b/Sources/NetworkCityCore/IPRanges.swift @@ -13,6 +13,16 @@ public enum IPRanges { ("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"), diff --git a/Tests/NetworkCityCoreTests/IPRangesTests.swift b/Tests/NetworkCityCoreTests/IPRangesTests.swift index 955e1d7..938b3ae 100644 --- a/Tests/NetworkCityCoreTests/IPRangesTests.swift +++ b/Tests/NetworkCityCoreTests/IPRangesTests.swift @@ -12,6 +12,14 @@ final class IPRangesTests: XCTestCase { XCTAssertEqual(IPRanges.match("149.154.175.54")?.key, "telegram") } + func testOneDriveNoPTRRangesCollapseToMicrosoft() { + // Real OneDrive front-end IPs (no PTR) that used to fragment per-IP. + XCTAssertEqual(IPRanges.match("13.107.137.11")?.key, "microsoft") + XCTAssertEqual(IPRanges.match("150.171.22.11")?.name, "Microsoft") + XCTAssertEqual(IPRanges.match("52.108.1.1")?.key, "microsoft") + XCTAssertEqual(IPRanges.match("40.96.0.1")?.key, "microsoft") + } + func testPrivateRangesAreLocalNetwork() { XCTAssertEqual(IPRanges.match("192.168.0.1")?.name, "Local Network") XCTAssertEqual(IPRanges.match("10.1.2.3")?.key, "lan")