Issue #1699 - Part 1: python/psutil: Support recent FreeBSD versions

'sysctl' interface to currently opened connections changed in FreeBSD 12.

Drop support for FreeBSD < 9, these are very old and unsupported versions.
This commit is contained in:
Olivier Certner 2021-01-06 10:31:19 +01:00 • committed by roytam1
commit 729af0b142
2 changed files with 76 additions and 13 deletions

View file

@ -38,7 +38,7 @@
#include <netinet/tcp_fsm.h> // for TCP connection states #include <netinet/tcp_fsm.h> // for TCP connection states
#include <arpa/inet.h> // for inet_ntop() #include <arpa/inet.h> // for inet_ntop()
#if __FreeBSD_version < 900000 #if !defined(__FreeBSD_version)
#include <utmp.h> // system users #include <utmp.h> // system users
#else #else
#include <utmpx.h> #include <utmpx.h>
@ -601,11 +601,7 @@ psutil_virtual_mem(PyObject *self, PyObject *args)
struct vmtotal vm; struct vmtotal vm;
int mib[] = {CTL_VM, VM_METER}; int mib[] = {CTL_VM, VM_METER};
long pagesize = getpagesize(); long pagesize = getpagesize();
#if __FreeBSD_version > 702101
long buffers; long buffers;
#else
int buffers;
#endif
size_t buffers_size = sizeof(buffers); size_t buffers_size = sizeof(buffers);
if (sysctlbyname("vm.stats.vm.v_page_count", &total, &size, NULL, 0)) if (sysctlbyname("vm.stats.vm.v_page_count", &total, &size, NULL, 0))
@ -724,13 +720,13 @@ psutil_cpu_times(PyObject *self, PyObject *args)
/* /*
* XXX * XXX
* These functions are available on FreeBSD 8 only. * These functions were seen available on FreeBSD only.
* In the upper python layer we do various tricks to avoid crashing * In the upper python layer we do various tricks to avoid crashing
* and/or to provide alternatives where possible. * and/or to provide alternatives where possible.
*/ */
#if defined(__FreeBSD_version) && __FreeBSD_version >= 800000 #if defined(__FreeBSD_version)
/* /*
* Return files opened by process as a list of (path, fd) tuples. * Return files opened by process as a list of (path, fd) tuples.
* TODO: this is broken as it may report empty paths. 'procstat' * TODO: this is broken as it may report empty paths. 'procstat'
@ -943,11 +939,19 @@ psutil_sockaddr_matches(int family, int port, void *pcb_addr,
psutil_sockaddr_addrlen(family)) == 0); psutil_sockaddr_addrlen(family)) == 0);
} }
#if __FreeBSD_version >= 1200026
static struct xtcpcb *
psutil_search_tcplist(char *buf, struct kinfo_file *kif)
{
struct xtcpcb *tp;
struct xinpcb *inp;
#else
static struct tcpcb * static struct tcpcb *
psutil_search_tcplist(char *buf, struct kinfo_file *kif) psutil_search_tcplist(char *buf, struct kinfo_file *kif)
{ {
struct tcpcb *tp; struct tcpcb *tp;
struct inpcb *inp; struct inpcb *inp;
#endif
struct xinpgen *xig, *oxig; struct xinpgen *xig, *oxig;
struct xsocket *so; struct xsocket *so;
@ -955,9 +959,15 @@ psutil_search_tcplist(char *buf, struct kinfo_file *kif)
for (xig = (struct xinpgen *)((char *)xig + xig->xig_len); for (xig = (struct xinpgen *)((char *)xig + xig->xig_len);
xig->xig_len > sizeof(struct xinpgen); xig->xig_len > sizeof(struct xinpgen);
xig = (struct xinpgen *)((char *)xig + xig->xig_len)) { xig = (struct xinpgen *)((char *)xig + xig->xig_len)) {
#if __FreeBSD_version >= 1200026
tp = (struct xtcpcb *)xig;
inp = &tp->xt_inp;
so = &inp->xi_socket;
#else
tp = &((struct xtcpcb *)xig)->xt_tp; tp = &((struct xtcpcb *)xig)->xt_tp;
inp = &((struct xtcpcb *)xig)->xt_inp; inp = &((struct xtcpcb *)xig)->xt_inp;
so = &((struct xtcpcb *)xig)->xt_socket; so = &((struct xtcpcb *)xig)->xt_socket;
#endif
if (so->so_type != kif->kf_sock_type || if (so->so_type != kif->kf_sock_type ||
so->xso_family != kif->kf_sock_domain || so->xso_family != kif->kf_sock_domain ||
@ -967,20 +977,36 @@ psutil_search_tcplist(char *buf, struct kinfo_file *kif)
if (kif->kf_sock_domain == AF_INET) { if (kif->kf_sock_domain == AF_INET) {
if (!psutil_sockaddr_matches( if (!psutil_sockaddr_matches(
AF_INET, inp->inp_lport, &inp->inp_laddr, AF_INET, inp->inp_lport, &inp->inp_laddr,
#if __FreeBSD_version < 1200031
&kif->kf_sa_local)) &kif->kf_sa_local))
#else
&kif->kf_un.kf_sock.kf_sa_local))
#endif
continue; continue;
if (!psutil_sockaddr_matches( if (!psutil_sockaddr_matches(
AF_INET, inp->inp_fport, &inp->inp_faddr, AF_INET, inp->inp_fport, &inp->inp_faddr,
#if __FreeBSD_version < 1200031
&kif->kf_sa_peer)) &kif->kf_sa_peer))
#else
&kif->kf_un.kf_sock.kf_sa_peer))
#endif
continue; continue;
} else { } else {
if (!psutil_sockaddr_matches( if (!psutil_sockaddr_matches(
AF_INET6, inp->inp_lport, &inp->in6p_laddr, AF_INET6, inp->inp_lport, &inp->in6p_laddr,
#if __FreeBSD_version < 1200031
&kif->kf_sa_local)) &kif->kf_sa_local))
#else
&kif->kf_un.kf_sock.kf_sa_local))
#endif
continue; continue;
if (!psutil_sockaddr_matches( if (!psutil_sockaddr_matches(
AF_INET6, inp->inp_fport, &inp->in6p_faddr, AF_INET6, inp->inp_fport, &inp->in6p_faddr,
#if __FreeBSD_version < 1200031
&kif->kf_sa_peer)) &kif->kf_sa_peer))
#else
&kif->kf_un.kf_sock.kf_sa_peer))
#endif
continue; continue;
} }
@ -1005,7 +1031,11 @@ psutil_proc_connections(PyObject *self, PyObject *args)
struct kinfo_file *freep = NULL; struct kinfo_file *freep = NULL;
struct kinfo_file *kif; struct kinfo_file *kif;
char *tcplist = NULL; char *tcplist = NULL;
#if __FreeBSD_version >= 1200026
struct xtcpcb *tcp;
#else
struct tcpcb *tcp; struct tcpcb *tcp;
#endif
PyObject *retList = PyList_New(0); PyObject *retList = PyList_New(0);
PyObject *tuple = NULL; PyObject *tuple = NULL;
@ -1074,19 +1104,35 @@ psutil_proc_connections(PyObject *self, PyObject *args)
inet_ntop( inet_ntop(
kif->kf_sock_domain, kif->kf_sock_domain,
psutil_sockaddr_addr(kif->kf_sock_domain, psutil_sockaddr_addr(kif->kf_sock_domain,
#if __FreeBSD_version < 1200031
&kif->kf_sa_local), &kif->kf_sa_local),
#else
&kif->kf_un.kf_sock.kf_sa_local),
#endif
lip, lip,
sizeof(lip)); sizeof(lip));
inet_ntop( inet_ntop(
kif->kf_sock_domain, kif->kf_sock_domain,
psutil_sockaddr_addr(kif->kf_sock_domain, psutil_sockaddr_addr(kif->kf_sock_domain,
#if __FreeBSD_version < 1200031
&kif->kf_sa_peer), &kif->kf_sa_peer),
#else
&kif->kf_un.kf_sock.kf_sa_peer),
#endif
rip, rip,
sizeof(rip)); sizeof(rip));
lport = htons(psutil_sockaddr_port(kif->kf_sock_domain, lport = htons(psutil_sockaddr_port(kif->kf_sock_domain,
#if __FreeBSD_version < 1200031
&kif->kf_sa_local)); &kif->kf_sa_local));
#else
&kif->kf_un.kf_sock.kf_sa_local));
#endif
rport = htons(psutil_sockaddr_port(kif->kf_sock_domain, rport = htons(psutil_sockaddr_port(kif->kf_sock_domain,
#if __FreeBSD_version < 1200031
&kif->kf_sa_peer)); &kif->kf_sa_peer));
#else
&kif->kf_un.kf_sock.kf_sa_peer));
#endif
// construct python tuple/list // construct python tuple/list
laddr = Py_BuildValue("(si)", lip, lport); laddr = Py_BuildValue("(si)", lip, lport);
@ -1115,7 +1161,11 @@ psutil_proc_connections(PyObject *self, PyObject *args)
else if (kif->kf_sock_domain == AF_UNIX) { else if (kif->kf_sock_domain == AF_UNIX) {
struct sockaddr_un *sun; struct sockaddr_un *sun;
#if __FreeBSD_version < 1200031
sun = (struct sockaddr_un *)&kif->kf_sa_local; sun = (struct sockaddr_un *)&kif->kf_sa_local;
#else
sun = (struct sockaddr_un *)&kif->kf_un.kf_sock.kf_sa_local;
#endif
snprintf( snprintf(
path, sizeof(path), "%.*s", path, sizeof(path), "%.*s",
(int)(sun->sun_len - (sizeof(*sun) - sizeof(sun->sun_path))), (int)(sun->sun_len - (sizeof(*sun) - sizeof(sun->sun_path))),
@ -1626,7 +1676,7 @@ psutil_users(PyObject *self, PyObject *args)
if (ret_list == NULL) if (ret_list == NULL)
return NULL; return NULL;
#if __FreeBSD_version < 900000 #if !defined(__FreeBSD_version)
struct utmp ut; struct utmp ut;
FILE *fp; FILE *fp;
@ -1736,7 +1786,7 @@ psutil_get_pid_from_sock(int sock_hash)
struct xfile *xf; struct xfile *xf;
int hash, n; int hash, n;
for (xf = psutil_xfiles, n = 0; n < psutil_nxfiles; ++n, ++xf) { for (xf = psutil_xfiles, n = 0; n < psutil_nxfiles; ++n, ++xf) {
if (xf->xf_data == NULL) if (xf->xf_data == 0)
continue; continue;
hash = (int)((uintptr_t)xf->xf_data % HASHSIZE); hash = (int)((uintptr_t)xf->xf_data % HASHSIZE);
if (sock_hash == hash) if (sock_hash == hash)
@ -1754,7 +1804,11 @@ int psutil_gather_inet(int proto, PyObject *py_retlist)
struct xinpgen *xig, *exig; struct xinpgen *xig, *exig;
struct xinpcb *xip; struct xinpcb *xip;
struct xtcpcb *xtp; struct xtcpcb *xtp;
#if defined(__FreeBSD_version) && __FreeBSD_version >= 1200026
struct xinpcb *inp;
#else
struct inpcb *inp; struct inpcb *inp;
#endif
struct xsocket *so; struct xsocket *so;
const char *varname = NULL; const char *varname = NULL;
size_t len, bufsize; size_t len, bufsize;
@ -1820,8 +1874,13 @@ int psutil_gather_inet(int proto, PyObject *py_retlist)
goto error; goto error;
} }
inp = &xtp->xt_inp; inp = &xtp->xt_inp;
#if defined(__FreeBSD_version) && __FreeBSD_version >= 1200026
so = &inp->xi_socket;
status = xtp->t_state;
#else
so = &xtp->xt_socket; so = &xtp->xt_socket;
status = xtp->xt_tp.t_state; status = xtp->xt_tp.t_state;
#endif
break; break;
case IPPROTO_UDP: case IPPROTO_UDP:
xip = (struct xinpcb *)xig; xip = (struct xinpcb *)xig;
@ -1830,7 +1889,11 @@ int psutil_gather_inet(int proto, PyObject *py_retlist)
"struct xinpcb size mismatch"); "struct xinpcb size mismatch");
goto error; goto error;
} }
#if defined(__FreeBSD_version) && __FreeBSD_version >= 1200026
inp = xip;
#else
inp = &xip->xi_inp; inp = &xip->xi_inp;
#endif
so = &xip->xi_socket; so = &xip->xi_socket;
status = PSUTIL_CONN_NONE; status = PSUTIL_CONN_NONE;
break; break;
@ -2166,7 +2229,7 @@ PsutilMethods[] =
"Return process CPU affinity."}, "Return process CPU affinity."},
{"proc_cpu_affinity_set", psutil_proc_cpu_affinity_set, METH_VARARGS, {"proc_cpu_affinity_set", psutil_proc_cpu_affinity_set, METH_VARARGS,
"Set process CPU affinity."}, "Set process CPU affinity."},
#if defined(__FreeBSD_version) && __FreeBSD_version >= 800000 #if defined(__FreeBSD_version)
{"proc_open_files", psutil_proc_open_files, METH_VARARGS, {"proc_open_files", psutil_proc_open_files, METH_VARARGS,
"Return files opened by process as a list of (path, fd) tuples"}, "Return files opened by process as a list of (path, fd) tuples"},
{"proc_cwd", psutil_proc_cwd, METH_VARARGS, {"proc_cwd", psutil_proc_cwd, METH_VARARGS,
@ -2191,7 +2254,7 @@ PsutilMethods[] =
"Return swap mem stats"}, "Return swap mem stats"},
{"cpu_times", psutil_cpu_times, METH_VARARGS, {"cpu_times", psutil_cpu_times, METH_VARARGS,
"Return system cpu times as a tuple (user, system, nice, idle, irc)"}, "Return system cpu times as a tuple (user, system, nice, idle, irc)"},
#if defined(__FreeBSD_version) && __FreeBSD_version >= 800000 #if defined(__FreeBSD_version)
{"per_cpu_times", psutil_per_cpu_times, METH_VARARGS, {"per_cpu_times", psutil_per_cpu_times, METH_VARARGS,
"Return system per-cpu times as a list of tuples"}, "Return system per-cpu times as a list of tuples"},
#endif #endif

View file

@ -29,7 +29,7 @@ static PyObject* psutil_proc_uids(PyObject* self, PyObject* args);
static PyObject* psutil_proc_cpu_affinity_get(PyObject* self, PyObject* args); static PyObject* psutil_proc_cpu_affinity_get(PyObject* self, PyObject* args);
static PyObject* psutil_proc_cpu_affinity_set(PyObject* self, PyObject* args); static PyObject* psutil_proc_cpu_affinity_set(PyObject* self, PyObject* args);
#if defined(__FreeBSD_version) && __FreeBSD_version >= 800000 #if defined(__FreeBSD_version)
static PyObject* psutil_proc_open_files(PyObject* self, PyObject* args); static PyObject* psutil_proc_open_files(PyObject* self, PyObject* args);
static PyObject* psutil_proc_cwd(PyObject* self, PyObject* args); static PyObject* psutil_proc_cwd(PyObject* self, PyObject* args);
#endif #endif
@ -48,6 +48,6 @@ static PyObject* psutil_swap_mem(PyObject* self, PyObject* args);
static PyObject* psutil_users(PyObject* self, PyObject* args); static PyObject* psutil_users(PyObject* self, PyObject* args);
static PyObject* psutil_virtual_mem(PyObject* self, PyObject* args); static PyObject* psutil_virtual_mem(PyObject* self, PyObject* args);
#if defined(__FreeBSD_version) && __FreeBSD_version >= 800000 #if defined(__FreeBSD_version)
static PyObject* psutil_per_cpu_times(PyObject* self, PyObject* args); static PyObject* psutil_per_cpu_times(PyObject* self, PyObject* args);
#endif #endif