in ambari-metrics-host-monitoring/src/main/python/psutil/psutil/_psutil_bsd.c [1777:1911]
int psutil_gather_inet(int proto, PyObject *py_retlist)
{
struct xinpgen *xig, *exig;
struct xinpcb *xip;
struct xtcpcb *xtp;
struct inpcb *inp;
struct xsocket *so;
struct sock *sock;
const char *varname;
size_t len, bufsize;
void *buf;
int hash, retry, vflag, type;
PyObject *tuple = NULL;
PyObject *laddr = NULL;
PyObject *raddr = NULL;
switch (proto) {
case IPPROTO_TCP:
varname = "net.inet.tcp.pcblist";
type = SOCK_STREAM;
break;
case IPPROTO_UDP:
varname = "net.inet.udp.pcblist";
type = SOCK_DGRAM;
break;
}
buf = NULL;
bufsize = 8192;
retry = 5;
do {
for (;;) {
buf = realloc(buf, bufsize);
if (buf == NULL) {
// XXX
continue;
}
len = bufsize;
if (sysctlbyname(varname, buf, &len, NULL, 0) == 0)
break;
if (errno != ENOMEM) {
PyErr_SetFromErrno(0);
goto error;
}
bufsize *= 2;
}
xig = (struct xinpgen *)buf;
exig = (struct xinpgen *)(void *)((char *)buf + len - sizeof *exig);
if (xig->xig_len != sizeof *xig || exig->xig_len != sizeof *exig) {
PyErr_Format(PyExc_RuntimeError, "struct xinpgen size mismatch");
goto error;
}
} while (xig->xig_gen != exig->xig_gen && retry--);
for (;;) {
xig = (struct xinpgen *)(void *)((char *)xig + xig->xig_len);
if (xig >= exig)
break;
switch (proto) {
case IPPROTO_TCP:
xtp = (struct xtcpcb *)xig;
if (xtp->xt_len != sizeof *xtp) {
PyErr_Format(PyExc_RuntimeError, "struct xtcpcb size mismatch");
goto error;
}
break;
case IPPROTO_UDP:
xip = (struct xinpcb *)xig;
if (xip->xi_len != sizeof *xip) {
PyErr_Format(PyExc_RuntimeError, "struct xinpcb size mismatch");
goto error;
}
inp = &xip->xi_inp;
so = &xip->xi_socket;
break;
}
inp = &xtp->xt_inp;
so = &xtp->xt_socket;
char lip[200], rip[200];
int family, lport, rport, pid, status;
hash = (int)((uintptr_t)so->xso_so % HASHSIZE);
pid = psutil_get_pid_from_sock(hash);
if (pid < 0)
continue;
lport = ntohs(inp->inp_lport);
rport = ntohs(inp->inp_fport);
status = xtp->xt_tp.t_state;
if (inp->inp_vflag & INP_IPV4) {
family = AF_INET;
inet_ntop(AF_INET, &inp->inp_laddr.s_addr, lip, sizeof(lip));
inet_ntop(AF_INET, &inp->inp_faddr.s_addr, rip, sizeof(rip));
}
else if (inp->inp_vflag & INP_IPV6) {
family = AF_INET6;
inet_ntop(AF_INET6, &inp->in6p_laddr.s6_addr, lip, sizeof(lip));
inet_ntop(AF_INET6, &inp->in6p_faddr.s6_addr, rip, sizeof(rip));
}
// construct python tuple/list
laddr = Py_BuildValue("(si)", lip, lport);
if (!laddr)
goto error;
if (rport != 0) {
raddr = Py_BuildValue("(si)", rip, rport);
}
else {
raddr = Py_BuildValue("()");
}
if (!raddr)
goto error;
tuple = Py_BuildValue("(iiiNNii)", -1, family, type, laddr, raddr,
status, pid);
if (!tuple)
goto error;
if (PyList_Append(py_retlist, tuple))
goto error;
Py_DECREF(tuple);
}
free(buf);
return 1;
error:
Py_XDECREF(tuple);
Py_XDECREF(laddr);
Py_XDECREF(raddr);
free(buf);
return 0;
}