Files
navi/ios/NavisTunnel/TunFileDescriptor.swift
T
M4andCursor 7ceb3a5148
ci / test (macos-latest) (push) Waiting to run
ci / test (ubuntu-latest) (push) Waiting to run
ci / test (windows-latest) (push) Waiting to run
Release 3.8.2.13: iOS Packet Tunnel client and Clash URL subscriptions.
Add SwiftUI + Network Extension (LibXray/hev), parse Clash Meta YAML from subscription URLs into vless/trojan/hy2 share links, keep the selected server on connect, and ship Navis-3.8.2.13.ipa with versioned changelog.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-01 22:46:32 +03:00

43 lines
1.3 KiB
Swift

import Foundation
import Darwin
import NetworkExtension
enum TunFileDescriptor {
/// Locate the utun socket used by NEPacketTunnelProvider (unsupported but widely used).
static func find() -> Int32? {
if let fd = packetFlowKVO() {
return fd
}
return findUtunByGetsockopt()
}
private static func packetFlowKVO() -> Int32? {
// Caller may set via associated object; left for PacketTunnelProvider to try first.
nil
}
private static func findUtunByGetsockopt() -> Int32? {
var buf = [CChar](repeating: 0, count: Int(IFNAMSIZ))
let prefix = Array("utun".utf8CString.dropLast())
for fd: Int32 in 0...1024 {
var len = socklen_t(buf.count)
// SOL_LOCAL=0 / SYSPROTO_CONTROL path varies; use getsockopt(fd, 2, 2) like WireGuard/others.
if getsockopt(fd, 2, 2, &buf, &len) == 0 {
if buf.starts(with: prefix) {
return fd
}
}
}
return nil
}
}
extension NEPacketTunnelProvider {
func resolveTunnelFileDescriptor() -> Int32? {
if let fd = packetFlow.value(forKeyPath: "socket.fileDescriptor") as? Int32, fd >= 0 {
return fd
}
return TunFileDescriptor.find()
}
}