diff options
author | Giampaolo Rodola <g.rodola@gmail.com> | 2017-05-16 17:32:09 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-05-16 17:32:09 +0200 |
commit | 59749a716a18678a8296ce346652cf9bc8f75842 (patch) | |
tree | 72cab68de490454aacfde43dfa0087ad85d37559 | |
parent | 82760460d2f7f5dab3374b5e95a035cf69880ba8 (diff) | |
download | psutil-59749a716a18678a8296ce346652cf9bc8f75842.tar.gz |
Freebsd socks refactoring (#1073)
* freebsd: split socks.c into 2 separate files
* remove unused h files
* freebsd: split socks.c into 2 separate files
-rw-r--r-- | psutil/_psutil_bsd.c | 3 | ||||
-rw-r--r-- | psutil/arch/freebsd/proc_socks.c (renamed from psutil/arch/freebsd/socks.c) | 347 | ||||
-rw-r--r-- | psutil/arch/freebsd/proc_socks.h | 9 | ||||
-rw-r--r-- | psutil/arch/freebsd/sys_socks.c | 362 | ||||
-rw-r--r-- | psutil/arch/freebsd/sys_socks.h (renamed from psutil/arch/freebsd/socks.h) | 1 | ||||
-rwxr-xr-x | setup.py | 3 |
6 files changed, 380 insertions, 345 deletions
diff --git a/psutil/_psutil_bsd.c b/psutil/_psutil_bsd.c index 506666b4..217a95de 100644 --- a/psutil/_psutil_bsd.c +++ b/psutil/_psutil_bsd.c @@ -64,7 +64,8 @@ #ifdef PSUTIL_FREEBSD #include "arch/freebsd/specific.h" - #include "arch/freebsd/socks.h" + #include "arch/freebsd/sys_socks.h" + #include "arch/freebsd/proc_socks.h" #include <net/if_media.h> #include <devstat.h> // get io counters diff --git a/psutil/arch/freebsd/socks.c b/psutil/arch/freebsd/proc_socks.c index 8fcb45e5..de4142be 100644 --- a/psutil/arch/freebsd/socks.c +++ b/psutil/arch/freebsd/proc_socks.c @@ -3,35 +3,27 @@ * All rights reserved. * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. + * + * Retrieves per-process open socket connections. */ #include <Python.h> #include <sys/user.h> -#include <sys/file.h> #include <sys/socketvar.h> // for struct xsocket #include <sys/un.h> -#include <sys/unpcb.h> -#include <sys/types.h> #include <sys/sysctl.h> #include <netinet/in.h> // for xinpcb struct -#include <netinet/in_systm.h> -#include <netinet/ip.h> #include <netinet/in_pcb.h> -#include <netinet/tcp.h> -#include <netinet/tcp_timer.h> #include <netinet/tcp_var.h> // for struct xtcpcb -#include <netinet/tcp_fsm.h> // for TCP connection states #include <arpa/inet.h> // for inet_ntop() -#include <net/if_media.h> #include <libutil.h> #include "../../_psutil_common.h" #include "../../_psutil_posix.h" + // a signaler for connections without an actual status static int PSUTIL_CONN_NONE = 128; -static struct xfile *psutil_xfiles; -static int psutil_nxfiles; // The tcplist fetching and walking is borrowed from netstat/inet.c. @@ -171,342 +163,13 @@ psutil_search_tcplist(char *buf, struct kinfo_file *kif) { } -int -psutil_populate_xfiles() { - size_t len; - - if ((psutil_xfiles = malloc(len = sizeof *psutil_xfiles)) == NULL) { - PyErr_NoMemory(); - return 0; - } - while (sysctlbyname("kern.file", psutil_xfiles, &len, 0, 0) == -1) { - if (errno != ENOMEM) { - PyErr_SetFromErrno(0); - return 0; - } - len *= 2; - if ((psutil_xfiles = realloc(psutil_xfiles, len)) == NULL) { - PyErr_NoMemory(); - return 0; - } - } - if (len > 0 && psutil_xfiles->xf_size != sizeof *psutil_xfiles) { - PyErr_Format(PyExc_RuntimeError, "struct xfile size mismatch"); - return 0; - } - psutil_nxfiles = len / sizeof *psutil_xfiles; - return 1; -} - - -int -psutil_get_pid_from_sock(void *sock) { - struct xfile *xf; - int n; - - for (xf = psutil_xfiles, n = 0; n < psutil_nxfiles; ++n, ++xf) { - if (xf->xf_data == sock) - return xf->xf_pid; - } - return -1; -} - - -// Reference: -// https://github.com/freebsd/freebsd/blob/master/usr.bin/sockstat/sockstat.c -int psutil_gather_inet(int proto, PyObject *py_retlist) { - struct xinpgen *xig, *exig; - struct xinpcb *xip; - struct xtcpcb *xtp; -#if __FreeBSD_version >= 1200026 - struct xinpcb *inp; -#else - struct inpcb *inp; -#endif - struct xsocket *so; - const char *varname = NULL; - size_t len, bufsize; - void *buf; - int retry; - int type; - - PyObject *py_tuple = NULL; - PyObject *py_laddr = NULL; - PyObject *py_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) - continue; // XXX - 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 (;;) { - int lport, rport, pid, status, family; - - 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; - } - inp = &xtp->xt_inp; -#if __FreeBSD_version >= 1200026 - so = &inp->xi_socket; - status = xtp->t_state; -#else - so = &xtp->xt_socket; - status = xtp->xt_tp.t_state; -#endif - break; - case IPPROTO_UDP: - xip = (struct xinpcb *)xig; - if (xip->xi_len != sizeof *xip) { - PyErr_Format(PyExc_RuntimeError, - "struct xinpcb size mismatch"); - goto error; - } -#if __FreeBSD_version >= 1200026 - inp = xip; -#else - inp = &xip->xi_inp; -#endif - so = &xip->xi_socket; - status = PSUTIL_CONN_NONE; - break; - default: - PyErr_Format(PyExc_RuntimeError, "invalid proto"); - goto error; - } - - char lip[200], rip[200]; - - pid = psutil_get_pid_from_sock(so->xso_so); - if (pid < 0) - continue; - lport = ntohs(inp->inp_lport); - rport = ntohs(inp->inp_fport); - - 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 - py_laddr = Py_BuildValue("(si)", lip, lport); - if (!py_laddr) - goto error; - if (rport != 0) - py_raddr = Py_BuildValue("(si)", rip, rport); - else - py_raddr = Py_BuildValue("()"); - if (!py_raddr) - goto error; - py_tuple = Py_BuildValue( - "(iiiNNii)", - -1, // fd - family, // family - type, // type - py_laddr, // laddr - py_raddr, // raddr - status, // status - pid); // pid - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_DECREF(py_tuple); - } - - free(buf); - return 1; - -error: - Py_XDECREF(py_tuple); - Py_XDECREF(py_laddr); - Py_XDECREF(py_raddr); - free(buf); - return 0; -} - - -int psutil_gather_unix(int proto, PyObject *py_retlist) { - struct xunpgen *xug, *exug; - struct xunpcb *xup; - const char *varname = NULL; - const char *protoname = NULL; - size_t len; - size_t bufsize; - void *buf; - int retry; - int pid; - struct sockaddr_un *sun; - char path[PATH_MAX]; - - PyObject *py_tuple = NULL; - PyObject *py_lpath = NULL; - - switch (proto) { - case SOCK_STREAM: - varname = "net.local.stream.pcblist"; - protoname = "stream"; - break; - case SOCK_DGRAM: - varname = "net.local.dgram.pcblist"; - protoname = "dgram"; - break; - } - - buf = NULL; - bufsize = 8192; - retry = 5; - - do { - for (;;) { - buf = realloc(buf, bufsize); - if (buf == NULL) { - PyErr_NoMemory(); - goto error; - } - len = bufsize; - if (sysctlbyname(varname, buf, &len, NULL, 0) == 0) - break; - if (errno != ENOMEM) { - PyErr_SetFromErrno(0); - goto error; - } - bufsize *= 2; - } - xug = (struct xunpgen *)buf; - exug = (struct xunpgen *)(void *) - ((char *)buf + len - sizeof *exug); - if (xug->xug_len != sizeof *xug || exug->xug_len != sizeof *exug) { - PyErr_Format(PyExc_RuntimeError, "struct xinpgen size mismatch"); - goto error; - } - } while (xug->xug_gen != exug->xug_gen && retry--); - - for (;;) { - xug = (struct xunpgen *)(void *)((char *)xug + xug->xug_len); - if (xug >= exug) - break; - xup = (struct xunpcb *)xug; - if (xup->xu_len != sizeof *xup) - goto error; - - pid = psutil_get_pid_from_sock(xup->xu_socket.xso_so); - if (pid < 0) - continue; - - sun = (struct sockaddr_un *)&xup->xu_addr; - snprintf(path, sizeof(path), "%.*s", - (int)(sun->sun_len - (sizeof(*sun) - sizeof(sun->sun_path))), - sun->sun_path); - py_lpath = PyUnicode_DecodeFSDefault(path); - if (! py_lpath) - goto error; - - py_tuple = Py_BuildValue("(iiiOsii)", - -1, // fd - AF_UNIX, // family - proto, // type - py_lpath, // lpath - "", // rath - PSUTIL_CONN_NONE, // status - pid); // pid - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_DECREF(py_lpath); - Py_DECREF(py_tuple); - } - - free(buf); - return 1; - -error: - Py_XDECREF(py_tuple); - Py_XDECREF(py_lpath); - free(buf); - return 0; -} - - -PyObject* -psutil_net_connections(PyObject* self, PyObject* args) { - // Return system-wide open connections. - PyObject *py_retlist = PyList_New(0); - - if (py_retlist == NULL) - return NULL; - if (psutil_populate_xfiles() != 1) - goto error; - if (psutil_gather_inet(IPPROTO_TCP, py_retlist) == 0) - goto error; - if (psutil_gather_inet(IPPROTO_UDP, py_retlist) == 0) - goto error; - if (psutil_gather_unix(SOCK_STREAM, py_retlist) == 0) - goto error; - if (psutil_gather_unix(SOCK_DGRAM, py_retlist) == 0) - goto error; - - free(psutil_xfiles); - return py_retlist; - -error: - Py_DECREF(py_retlist); - free(psutil_xfiles); - return NULL; -} - PyObject * psutil_proc_connections(PyObject *self, PyObject *args) { // Return connections opened by process. long pid; - int i, cnt; + int i; + int cnt; struct kinfo_file *freep = NULL; struct kinfo_file *kif; char *tcplist = NULL; diff --git a/psutil/arch/freebsd/proc_socks.h b/psutil/arch/freebsd/proc_socks.h new file mode 100644 index 00000000..a7996b10 --- /dev/null +++ b/psutil/arch/freebsd/proc_socks.h @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include <Python.h> + +PyObject* psutil_proc_connections(PyObject* self, PyObject* args); diff --git a/psutil/arch/freebsd/sys_socks.c b/psutil/arch/freebsd/sys_socks.c new file mode 100644 index 00000000..4104c27d --- /dev/null +++ b/psutil/arch/freebsd/sys_socks.c @@ -0,0 +1,362 @@ +/* + * Copyright (c) 2009, Giampaolo Rodola'. + * All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Retrieves system-wide open socket connections. This is based off of + * sockstat utility source code: + * https://github.com/freebsd/freebsd/blob/master/usr.bin/sockstat/sockstat.c + */ + +#include <Python.h> +#include <sys/user.h> +#include <sys/file.h> +#include <sys/socketvar.h> // for struct xsocket +#include <sys/un.h> +#include <sys/unpcb.h> +#include <sys/sysctl.h> +#include <netinet/in.h> // for xinpcb struct +#include <netinet/ip.h> +#include <netinet/in_pcb.h> +#include <netinet/tcp_var.h> // for struct xtcpcb +#include <arpa/inet.h> // for inet_ntop() + +#include "../../_psutil_common.h" +#include "../../_psutil_posix.h" + +// a signaler for connections without an actual status +static int PSUTIL_CONN_NONE = 128; +static struct xfile *psutil_xfiles; +static int psutil_nxfiles; + + +int +psutil_populate_xfiles() { + size_t len; + + if ((psutil_xfiles = malloc(len = sizeof *psutil_xfiles)) == NULL) { + PyErr_NoMemory(); + return 0; + } + while (sysctlbyname("kern.file", psutil_xfiles, &len, 0, 0) == -1) { + if (errno != ENOMEM) { + PyErr_SetFromErrno(0); + return 0; + } + len *= 2; + if ((psutil_xfiles = realloc(psutil_xfiles, len)) == NULL) { + PyErr_NoMemory(); + return 0; + } + } + if (len > 0 && psutil_xfiles->xf_size != sizeof *psutil_xfiles) { + PyErr_Format(PyExc_RuntimeError, "struct xfile size mismatch"); + return 0; + } + psutil_nxfiles = len / sizeof *psutil_xfiles; + return 1; +} + + +int +psutil_get_pid_from_sock(void *sock) { + struct xfile *xf; + int n; + + for (xf = psutil_xfiles, n = 0; n < psutil_nxfiles; ++n, ++xf) { + if (xf->xf_data == sock) + return xf->xf_pid; + } + return -1; +} + + +// Reference: +// https://github.com/freebsd/freebsd/blob/master/usr.bin/sockstat/sockstat.c +int psutil_gather_inet(int proto, PyObject *py_retlist) { + struct xinpgen *xig, *exig; + struct xinpcb *xip; + struct xtcpcb *xtp; +#if __FreeBSD_version >= 1200026 + struct xinpcb *inp; +#else + struct inpcb *inp; +#endif + struct xsocket *so; + const char *varname = NULL; + size_t len, bufsize; + void *buf; + int retry; + int type; + + PyObject *py_tuple = NULL; + PyObject *py_laddr = NULL; + PyObject *py_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) + continue; // XXX + 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 (;;) { + int lport, rport, pid, status, family; + + 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; + } + inp = &xtp->xt_inp; +#if __FreeBSD_version >= 1200026 + so = &inp->xi_socket; + status = xtp->t_state; +#else + so = &xtp->xt_socket; + status = xtp->xt_tp.t_state; +#endif + break; + case IPPROTO_UDP: + xip = (struct xinpcb *)xig; + if (xip->xi_len != sizeof *xip) { + PyErr_Format(PyExc_RuntimeError, + "struct xinpcb size mismatch"); + goto error; + } +#if __FreeBSD_version >= 1200026 + inp = xip; +#else + inp = &xip->xi_inp; +#endif + so = &xip->xi_socket; + status = PSUTIL_CONN_NONE; + break; + default: + PyErr_Format(PyExc_RuntimeError, "invalid proto"); + goto error; + } + + char lip[200], rip[200]; + + pid = psutil_get_pid_from_sock(so->xso_so); + if (pid < 0) + continue; + lport = ntohs(inp->inp_lport); + rport = ntohs(inp->inp_fport); + + 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 + py_laddr = Py_BuildValue("(si)", lip, lport); + if (!py_laddr) + goto error; + if (rport != 0) + py_raddr = Py_BuildValue("(si)", rip, rport); + else + py_raddr = Py_BuildValue("()"); + if (!py_raddr) + goto error; + py_tuple = Py_BuildValue( + "(iiiNNii)", + -1, // fd + family, // family + type, // type + py_laddr, // laddr + py_raddr, // raddr + status, // status + pid); // pid + if (!py_tuple) + goto error; + if (PyList_Append(py_retlist, py_tuple)) + goto error; + Py_DECREF(py_tuple); + } + + free(buf); + return 1; + +error: + Py_XDECREF(py_tuple); + Py_XDECREF(py_laddr); + Py_XDECREF(py_raddr); + free(buf); + return 0; +} + + +int psutil_gather_unix(int proto, PyObject *py_retlist) { + struct xunpgen *xug, *exug; + struct xunpcb *xup; + const char *varname = NULL; + const char *protoname = NULL; + size_t len; + size_t bufsize; + void *buf; + int retry; + int pid; + struct sockaddr_un *sun; + char path[PATH_MAX]; + + PyObject *py_tuple = NULL; + PyObject *py_lpath = NULL; + + switch (proto) { + case SOCK_STREAM: + varname = "net.local.stream.pcblist"; + protoname = "stream"; + break; + case SOCK_DGRAM: + varname = "net.local.dgram.pcblist"; + protoname = "dgram"; + break; + } + + buf = NULL; + bufsize = 8192; + retry = 5; + + do { + for (;;) { + buf = realloc(buf, bufsize); + if (buf == NULL) { + PyErr_NoMemory(); + goto error; + } + len = bufsize; + if (sysctlbyname(varname, buf, &len, NULL, 0) == 0) + break; + if (errno != ENOMEM) { + PyErr_SetFromErrno(0); + goto error; + } + bufsize *= 2; + } + xug = (struct xunpgen *)buf; + exug = (struct xunpgen *)(void *) + ((char *)buf + len - sizeof *exug); + if (xug->xug_len != sizeof *xug || exug->xug_len != sizeof *exug) { + PyErr_Format(PyExc_RuntimeError, "struct xinpgen size mismatch"); + goto error; + } + } while (xug->xug_gen != exug->xug_gen && retry--); + + for (;;) { + xug = (struct xunpgen *)(void *)((char *)xug + xug->xug_len); + if (xug >= exug) + break; + xup = (struct xunpcb *)xug; + if (xup->xu_len != sizeof *xup) + goto error; + + pid = psutil_get_pid_from_sock(xup->xu_socket.xso_so); + if (pid < 0) + continue; + + sun = (struct sockaddr_un *)&xup->xu_addr; + snprintf(path, sizeof(path), "%.*s", + (int)(sun->sun_len - (sizeof(*sun) - sizeof(sun->sun_path))), + sun->sun_path); + py_lpath = PyUnicode_DecodeFSDefault(path); + if (! py_lpath) + goto error; + + py_tuple = Py_BuildValue("(iiiOsii)", + -1, // fd + AF_UNIX, // family + proto, // type + py_lpath, // lpath + "", // rath + PSUTIL_CONN_NONE, // status + pid); // pid + if (!py_tuple) + goto error; + if (PyList_Append(py_retlist, py_tuple)) + goto error; + Py_DECREF(py_lpath); + Py_DECREF(py_tuple); + } + + free(buf); + return 1; + +error: + Py_XDECREF(py_tuple); + Py_XDECREF(py_lpath); + free(buf); + return 0; +} + + +PyObject* +psutil_net_connections(PyObject* self, PyObject* args) { + // Return system-wide open connections. + PyObject *py_retlist = PyList_New(0); + + if (py_retlist == NULL) + return NULL; + if (psutil_populate_xfiles() != 1) + goto error; + if (psutil_gather_inet(IPPROTO_TCP, py_retlist) == 0) + goto error; + if (psutil_gather_inet(IPPROTO_UDP, py_retlist) == 0) + goto error; + if (psutil_gather_unix(SOCK_STREAM, py_retlist) == 0) + goto error; + if (psutil_gather_unix(SOCK_DGRAM, py_retlist) == 0) + goto error; + + free(psutil_xfiles); + return py_retlist; + +error: + Py_DECREF(py_retlist); + free(psutil_xfiles); + return NULL; +} diff --git a/psutil/arch/freebsd/socks.h b/psutil/arch/freebsd/sys_socks.h index 15ccb0b3..75247926 100644 --- a/psutil/arch/freebsd/socks.h +++ b/psutil/arch/freebsd/sys_socks.h @@ -7,5 +7,4 @@ #include <Python.h> -PyObject* psutil_proc_connections(PyObject* self, PyObject* args); PyObject* psutil_net_connections(PyObject* self, PyObject* args); @@ -169,7 +169,8 @@ elif FREEBSD: sources=sources + [ 'psutil/_psutil_bsd.c', 'psutil/arch/freebsd/specific.c', - 'psutil/arch/freebsd/socks.c', + 'psutil/arch/freebsd/sys_socks.c', + 'psutil/arch/freebsd/proc_socks.c', ], define_macros=macros, libraries=["devstat"]) |