|
Packit Service |
3880ab |
#include <stdio.h>
|
|
Packit Service |
3880ab |
#include <stdlib.h>
|
|
Packit Service |
3880ab |
#include <errno.h>
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
#include "libnetlink.h"
|
|
Packit Service |
3880ab |
#include "ssfilter.h"
|
|
Packit Service |
3880ab |
#include "ss_util.h"
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
static int dummy_filter(struct nlmsghdr *n, void *arg)
|
|
Packit Service |
3880ab |
{
|
|
Packit Service |
3880ab |
/* just stops rtnl_dump_filter() */
|
|
Packit Service |
3880ab |
return -1;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
static bool cgroup_filter_check(void)
|
|
Packit Service |
3880ab |
{
|
|
Packit Service |
3880ab |
struct sockaddr_nl nladdr = { .nl_family = AF_NETLINK };
|
|
Packit Service |
3880ab |
DIAG_REQUEST(req, struct inet_diag_req_v2 r);
|
|
Packit Service |
3880ab |
struct instr {
|
|
Packit Service |
3880ab |
struct inet_diag_bc_op op;
|
|
Packit Service |
3880ab |
__u64 cgroup_id;
|
|
Packit Service |
3880ab |
} __attribute__((packed));
|
|
Packit Service |
3880ab |
int inslen = sizeof(struct instr);
|
|
Packit Service |
3880ab |
struct instr instr = {
|
|
Packit Service |
3880ab |
{ INET_DIAG_BC_CGROUP_COND, inslen, inslen + 4 },
|
|
Packit Service |
3880ab |
0
|
|
Packit Service |
3880ab |
};
|
|
Packit Service |
3880ab |
struct rtnl_handle rth;
|
|
Packit Service |
3880ab |
struct iovec iov[3];
|
|
Packit Service |
3880ab |
struct msghdr msg;
|
|
Packit Service |
3880ab |
struct rtattr rta;
|
|
Packit Service |
3880ab |
int ret = false;
|
|
Packit Service |
3880ab |
int iovlen = 3;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (rtnl_open_byproto(&rth, 0, NETLINK_SOCK_DIAG))
|
|
Packit Service |
3880ab |
return false;
|
|
Packit Service |
3880ab |
rth.dump = MAGIC_SEQ;
|
|
Packit Service |
3880ab |
rth.flags = RTNL_HANDLE_F_SUPPRESS_NLERR;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
memset(&req.r, 0, sizeof(req.r));
|
|
Packit Service |
3880ab |
req.r.sdiag_family = AF_INET;
|
|
Packit Service |
3880ab |
req.r.sdiag_protocol = IPPROTO_TCP;
|
|
Packit Service |
3880ab |
req.nlh.nlmsg_len += RTA_LENGTH(inslen);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
rta.rta_type = INET_DIAG_REQ_BYTECODE;
|
|
Packit Service |
3880ab |
rta.rta_len = RTA_LENGTH(inslen);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
iov[0] = (struct iovec) { &req, sizeof(req) };
|
|
Packit Service |
3880ab |
iov[1] = (struct iovec) { &rta, sizeof(rta) };
|
|
Packit Service |
3880ab |
iov[2] = (struct iovec) { &instr, inslen };
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
msg = (struct msghdr) {
|
|
Packit Service |
3880ab |
.msg_name = (void *)&nladdr,
|
|
Packit Service |
3880ab |
.msg_namelen = sizeof(nladdr),
|
|
Packit Service |
3880ab |
.msg_iov = iov,
|
|
Packit Service |
3880ab |
.msg_iovlen = iovlen,
|
|
Packit Service |
3880ab |
};
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (sendmsg(rth.fd, &msg, 0) < 0)
|
|
Packit Service |
3880ab |
goto out;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (rtnl_dump_filter(&rth, dummy_filter, NULL) < 0) {
|
|
Packit Service |
3880ab |
ret = (errno != EINVAL);
|
|
Packit Service |
3880ab |
goto out;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
ret = true;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
out:
|
|
Packit Service |
3880ab |
rtnl_close(&rth);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
return ret;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
struct filter_check_t {
|
|
Packit Service |
3880ab |
bool (*check)(void);
|
|
Packit Service |
3880ab |
int checked:1,
|
|
Packit Service |
3880ab |
supported:1;
|
|
Packit Service |
3880ab |
};
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
static struct filter_check_t filter_checks[SSF__MAX] = {
|
|
Packit Service |
3880ab |
[SSF_CGROUPCOND] = { cgroup_filter_check, 0 },
|
|
Packit Service |
3880ab |
};
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
bool ssfilter_is_supported(int type)
|
|
Packit Service |
3880ab |
{
|
|
Packit Service |
3880ab |
struct filter_check_t f;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (type >= SSF__MAX)
|
|
Packit Service |
3880ab |
return false;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
f = filter_checks[type];
|
|
Packit Service |
3880ab |
if (!f.check)
|
|
Packit Service |
3880ab |
return true;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (!f.checked) {
|
|
Packit Service |
3880ab |
f.supported = f.check();
|
|
Packit Service |
3880ab |
f.checked = 1;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
return f.supported;
|
|
Packit Service |
3880ab |
}
|