Blame misc/ssfilter_check.c

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
}