]> git.proxmox.com Git - mirror_iproute2.git/blame - misc/ssfilter_check.c
Merge branch 'gcc-10' into main
[mirror_iproute2.git] / misc / ssfilter_check.c
CommitLineData
7bd91885
DY
1#include <stdio.h>
2#include <stdlib.h>
3#include <errno.h>
4
5#include "libnetlink.h"
6#include "ssfilter.h"
7#include "ss_util.h"
8
9static int dummy_filter(struct nlmsghdr *n, void *arg)
10{
11 /* just stops rtnl_dump_filter() */
12 return -1;
13}
14
15static bool cgroup_filter_check(void)
16{
17 struct sockaddr_nl nladdr = { .nl_family = AF_NETLINK };
18 DIAG_REQUEST(req, struct inet_diag_req_v2 r);
19 struct instr {
20 struct inet_diag_bc_op op;
21 __u64 cgroup_id;
22 } __attribute__((packed));
23 int inslen = sizeof(struct instr);
24 struct instr instr = {
25 { INET_DIAG_BC_CGROUP_COND, inslen, inslen + 4 },
26 0
27 };
28 struct rtnl_handle rth;
29 struct iovec iov[3];
30 struct msghdr msg;
31 struct rtattr rta;
32 int ret = false;
33 int iovlen = 3;
34
35 if (rtnl_open_byproto(&rth, 0, NETLINK_SOCK_DIAG))
36 return false;
37 rth.dump = MAGIC_SEQ;
38 rth.flags = RTNL_HANDLE_F_SUPPRESS_NLERR;
39
40 memset(&req.r, 0, sizeof(req.r));
41 req.r.sdiag_family = AF_INET;
42 req.r.sdiag_protocol = IPPROTO_TCP;
43 req.nlh.nlmsg_len += RTA_LENGTH(inslen);
44
45 rta.rta_type = INET_DIAG_REQ_BYTECODE;
46 rta.rta_len = RTA_LENGTH(inslen);
47
48 iov[0] = (struct iovec) { &req, sizeof(req) };
49 iov[1] = (struct iovec) { &rta, sizeof(rta) };
50 iov[2] = (struct iovec) { &instr, inslen };
51
52 msg = (struct msghdr) {
53 .msg_name = (void *)&nladdr,
54 .msg_namelen = sizeof(nladdr),
55 .msg_iov = iov,
56 .msg_iovlen = iovlen,
57 };
58
59 if (sendmsg(rth.fd, &msg, 0) < 0)
60 goto out;
61
62 if (rtnl_dump_filter(&rth, dummy_filter, NULL) < 0) {
63 ret = (errno != EINVAL);
64 goto out;
65 }
66
67 ret = true;
68
69out:
70 rtnl_close(&rth);
71
72 return ret;
73}
74
75
76struct filter_check_t {
77 bool (*check)(void);
78 int checked:1,
79 supported:1;
80};
81
82static struct filter_check_t filter_checks[SSF__MAX] = {
83 [SSF_CGROUPCOND] = { cgroup_filter_check, 0 },
84};
85
86bool ssfilter_is_supported(int type)
87{
88 struct filter_check_t f;
89
90 if (type >= SSF__MAX)
91 return false;
92
93 f = filter_checks[type];
94 if (!f.check)
95 return true;
96
97 if (!f.checked) {
98 f.supported = f.check();
99 f.checked = 1;
100 }
101
102 return f.supported;
103}