Last active
June 13, 2024 22:33
-
-
Save stephancasas/8eacb20e88afc2e556a689f422778aa3 to your computer and use it in GitHub Desktop.
Get a list of macOS' in-use network ports.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation; | |
/// Copy the list of in-use network ports — optionally filtering by the ports' state. | |
/// - Parameters: | |
/// - buffer: The buffer into which the port list will populate | |
/// - state: The port state by which to filter. | |
/// - Returns: Expect `KERN_SUCCESS` if the operation was successful. | |
@discardableResult | |
func sysctl_inet_ports_list_copy(_ buffer: UnsafeMutablePointer<[UInt16]>, _ state: Int32? = nil) -> kern_return_t { | |
var kern_return: kern_return_t; | |
// How big does the buffer need to be to acquire the information we're going to get? | |
var mgmt_info_size = 0; | |
kern_return = sysctlbyname("net.inet.tcp.pcblist", nil, &mgmt_info_size, nil, 0); | |
guard kern_return == KERN_SUCCESS else { | |
return kern_return; | |
} | |
// Create and fill that buffer. | |
var sysctl_result_buf = [UInt8](repeating: 0, count: mgmt_info_size); | |
kern_return = sysctlbyname("net.inet.tcp.pcblist", &sysctl_result_buf, &mgmt_info_size, nil, 0); | |
guard kern_return == KERN_SUCCESS else { | |
return kern_return; | |
} | |
// Loop through the structured buffer of PCBs and extract each port — optionally filtering by state. | |
sysctl_result_buf.withUnsafeBytes({ ptr in | |
var pcbAddr = ptr.baseAddress!; | |
var pcbHeader = pcbAddr.bindMemory(to: xinpgen.self, capacity: 1); | |
while Int(pcbHeader.pointee.xig_len) >= MemoryLayout<xinpgen>.size { | |
let tcp_pcb = pcbHeader.withMemoryRebound(to: xtcpcb.self, capacity: 1, { | |
$0.pointee | |
}); | |
if state == nil || (state != nil && state! == tcp_pcb.xt_tp.t_state) { | |
buffer.pointee.append(_OSSwapInt16(tcp_pcb.xt_inp.inp_lport)); | |
} | |
pcbAddr += .init(pcbHeader.pointee.xig_len); | |
pcbHeader = pcbAddr.bindMemory(to: xinpgen.self, capacity: 1); | |
} | |
}) | |
return kern_return; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment