int psutil_gather_inet()

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;
}