iproute2/misc/ssfilter_check.c
<<
>>
Prefs
   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}
 104