Skip to content

Instantly share code, notes, and snippets.

@nythepegasus
Last active February 27, 2026 05:27
Show Gist options
  • Select an option

  • Save nythepegasus/fd8ee8d2f0dba03e66f227d6137caab1 to your computer and use it in GitHub Desktop.

Select an option

Save nythepegasus/fd8ee8d2f0dba03e66f227d6137caab1 to your computer and use it in GitHub Desktop.
Network interface helper in Swift
// authored by @nythepegasus
// with help from others
public struct NetInfo: Hashable {
public let name: String
public let host: String
public let dest: String?
public let mask: String
public init(name: String, host: String, dest: String?, mask: String) {
self.name = name
self.host = host
self.dest = dest
self.mask = mask
}
private init?(_ addr: ifaddrs) {
guard var hostaddr = addr.ifa_addr?.pointee,
var destaddr = addr.ifa_dstaddr?.pointee,
var maskaddr = addr.ifa_netmask?.pointee,
let name = String(utf8String: addr.ifa_name),
let host = NetInfo.sockname(&hostaddr),
let mask = NetInfo.sockname(&maskaddr) else { return nil }
self = .init(name: name, host: host, dest: NetInfo.sockname(&destaddr), mask: mask)
}
private static func sockname(_ sock: inout sockaddr) -> String? {
var buf = [CChar](repeating: 0, count: Int(NI_MAXHOST))
guard getnameinfo(&sock, socklen_t(sock.sa_len), &buf, socklen_t(buf.count), nil, socklen_t(0), NI_NUMERICHOST) == 0,
let str = String(utf8String: buf) else {
return nil
}
return str
}
public static func addrs(_ check: (ifaddrs) -> Bool = { _ in true }) -> Set<NetInfo> {
var addresses = Set<NetInfo>()
var head: UnsafeMutablePointer<ifaddrs>? = nil
guard getifaddrs(&head) == 0, let first = head else { return addresses }
defer { freeifaddrs(head) }
var ifaddr: UnsafeMutablePointer<ifaddrs>? = first
while let next = ifaddr {
if let info = NetInfo(next.pointee),
check(next.pointee) { addresses.insert(info) }
ifaddr = next.pointee.ifa_next
}
return addresses
}
public static func v4addrs() -> Set<NetInfo> {
addrs { ifaddr in
(ifaddr.ifa_addr.pointee.sa_family == UInt8(AF_INET)) &&
(Int32(ifaddr.ifa_flags) & (IFF_UP|IFF_RUNNING|IFF_LOOPBACK)) == (IFF_UP|IFF_RUNNING)
}
}
public static func nextOpenV4() -> NetInfo? {
v4addrs().first { $0.mask != "255.255.255.255" && $0.host != "10.7.0.0" }
}
public static func sideVPN() -> NetInfo? {
addrs().first { $0.host == "10.7.0.0" }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment