Skip to content

Instantly share code, notes, and snippets.

@stephancasas
Last active June 13, 2024 22:33
Show Gist options
  • Save stephancasas/8eacb20e88afc2e556a689f422778aa3 to your computer and use it in GitHub Desktop.
Save stephancasas/8eacb20e88afc2e556a689f422778aa3 to your computer and use it in GitHub Desktop.
Get a list of macOS' in-use network ports.
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