tethering-hider/TetheringHider/Models/TTLManager.swift
2026-08-12 23:44:59 -05:00

64 lines
1.8 KiB
Swift

import Foundation
import Observation
@Observable
@MainActor
final class TTLManager {
private(set) var currentTTL: Int = 64
private(set) var currentIPv6HopLimit: Int = 64
private(set) var isProtected: Bool = false
private(set) var lastError: String?
var onStatusChanged: (() -> Void)?
let defaultTTL: Int = 64
let targetTTL: Int = 65
init() {
refreshStatus()
}
/// Reads the current system IPv4 TTL value using sysctlbyname (no root required)
func readCurrentTTL() -> Int {
var ttl: Int32 = 0
var size = MemoryLayout<Int32>.size
let result = sysctlbyname("net.inet.ip.ttl", &ttl, &size, nil, 0)
if result == 0 {
return Int(ttl)
}
return defaultTTL
}
/// Reads the current system IPv6 Hop Limit value using sysctlbyname (no root required)
func readCurrentIPv6HopLimit() -> Int {
var hlim: Int32 = 0
var size = MemoryLayout<Int32>.size
let result = sysctlbyname("net.inet6.ip6.hlim", &hlim, &size, nil, 0)
if result == 0 {
return Int(hlim)
}
return defaultTTL
}
/// Refreshes current IPv4 TTL, IPv6 Hop Limit, and protection status
func refreshStatus() {
currentTTL = readCurrentTTL()
currentIPv6HopLimit = readCurrentIPv6HopLimit()
isProtected = (currentTTL == targetTTL) && (currentIPv6HopLimit == targetTTL)
lastError = nil
onStatusChanged?()
}
func didSetTTL(_ value: Int) {
currentTTL = value
currentIPv6HopLimit = value
isProtected = value == targetTTL
lastError = nil
onStatusChanged?()
}
func setError(_ message: String) {
lastError = message
onStatusChanged?()
}
}