diff --git a/src/os/darwin/darwin_sigar.c b/src/os/darwin/darwin_sigar.c index 1b1284a6..445f5460 100644 --- a/src/os/darwin/darwin_sigar.c +++ b/src/os/darwin/darwin_sigar.c @@ -1536,6 +1536,123 @@ int sigar_net_connection_list_get(sigar_t *sigar, return SIGAR_OK; } +#define _KERNEL +#include +#undef _KERNEL + +/* derived from + * /usr/ports/security/pidentd/work/pidentd-3.0.16/src/k_freebsd2.c + */ +int sigar_proc_port_get(sigar_t *sigar, int protocol, + unsigned long port, sigar_pid_t *pid) +{ + struct nlist nl[2]; + struct inpcbhead tcb; + struct socket *sockp = NULL; + struct kinfo_proc *pinfo; + struct inpcb *head, pcbp; + int i, nentries, status; + + if (protocol != SIGAR_NETCONN_TCP) { + return SIGAR_ENOTIMPL; + } + + if (!sigar->kmem) { + return EPERM; + } + + nl[0].n_name = "_tcb"; /* XXX cache */ + if (kvm_nlist(sigar->kmem, nl) < 0) { + return errno; + } + + status = kread(sigar, &tcb, sizeof(tcb), nl[0].n_value); + if (status != SIGAR_OK) { + return status; + } + + for (head = tcb.lh_first; head != NULL; + head = pcbp.inp_list.le_next) + { + status = kread(sigar, &pcbp, sizeof(pcbp), (long)head); + if (status != SIGAR_OK) { + return status; + } + if (!(pcbp.inp_vflag & INP_IPV4)) { + continue; + } + if (pcbp.inp_fport != 0) { + continue; + } + if (ntohs(pcbp.inp_lport) == port) { + sockp = pcbp.inp_socket; + break; + } + } + + if (!sockp) { + return ENOENT; + } + + pinfo = kvm_getprocs(sigar->kmem, KERN_PROC_ALL, 0, &nentries); + if (!pinfo) { + return errno; + } + + for (i=0; i