]>
Commit | Line | Data |
---|---|---|
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 | ||
9 | static int dummy_filter(struct nlmsghdr *n, void *arg) | |
10 | { | |
11 | /* just stops rtnl_dump_filter() */ | |
12 | return -1; | |
13 | } | |
14 | ||
15 | static 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 | ||
69 | out: | |
70 | rtnl_close(&rth); | |
71 | ||
72 | return ret; | |
73 | } | |
74 | ||
75 | ||
76 | struct filter_check_t { | |
77 | bool (*check)(void); | |
78 | int checked:1, | |
79 | supported:1; | |
80 | }; | |
81 | ||
82 | static struct filter_check_t filter_checks[SSF__MAX] = { | |
83 | [SSF_CGROUPCOND] = { cgroup_filter_check, 0 }, | |
84 | }; | |
85 | ||
86 | bool 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 | } |