使用netlink从较旧内核上的套接字获取索引节点

问题描述 投票:0回答:1

我编写了一段代码,以使用sock_diag netlink获取套接字及其索引节点的列表。这是发送代码:

struct {
  nlmsghdr nlh;
  inet_diag_req_v2 id_req;
} req = {
  .nlh = {
    .nlmsg_len = sizeof(req),
    .nlmsg_type = SOCK_DIAG_BY_FAMILY,
    .nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP
  },
  .id_req = {
    .sdiag_family = AF_INET,
    .sdiag_protocol = IPPROTO_TCP,
    .idiag_ext = uint8_t(0),
    .pad = uint8_t(0),
    .idiag_states = UINT32_MAX // Everything
  }
};
struct sockaddr_nl nladdr = {
  .nl_family = AF_NETLINK
};
struct iovec iov = {
  .iov_base = &req,
  .iov_len = sizeof(req)
};
struct msghdr msg = {
  .msg_name = (void *) &nladdr,
  .msg_namelen = sizeof(nladdr),
  .msg_iov = &iov,
  .msg_iovlen = 1
};

// Send message to kernel
for (;;) {
  if (sendmsg(query_fd_, &msg, 0) < 0) {
    if (errno == EINTR)
      continue;

    perror("sendmsg");
    return false;
  }
  return;
}

[不幸的是,我们用于构建的机器之一仍在运行RHEL6.8(2.6.32-642),这意味着它没有<linux/sock_diag.h>SOCK_DIAG_BY_FAMILYinet_diag_req_v2结构。

通过查看较旧内核的内核头和手册页,我可以看到我们有inet_diag_req选项,它与更新的结构相当接近。我尝试像这样直接替换:

#define SOCK_DIAG_BY_FAMILY 20

struct {
      nlmsghdr nlh;
      inet_diag_req id_req;
    } req = {
      .nlh = {
         .nlmsg_len = sizeof(req),
         .nlmsg_type = SOCK_DIAG_BY_FAMILY,
         .nlmsg_flags = NLM_F_REQUEST
      },
      .id_req = {
        .idiag_family = AF_INET,
        .idiag_src_len = uint8_t(0),
        .idiag_dst_len = uint8_t(0),
        .idiag_ext = uint8_t(0),
        .id = {},
        .idiag_states = UINT32_MAX // Everything
      }
    };
.
.

我返回状态为NLMSG_ERROR: No such file or directory的消息。

我正在努力寻找ANY我正在尝试做的事的例子。是否可以使用较旧的inet_diag_req消息基于协议和家族检索套接字列表,如果是,则知道我在做什么错吗?

c sockets kernel netlink
1个回答
0
投票

我发布的代码实际上可以按预期工作,但是必须在较旧的机器(内核<3)上构建并运行。我启动了一个真正的RH6.8计算机,构建并运行了代码,我得到了正确的响应,但是在内核> = 3的计算机上,它返回了错误。我误解了docker,并认为我的容器具有自己的内核,但实际上使用的主机导致了一些混乱。

摘要:

内核<3使用inet_diag_req。

内核> = 3使用inet_diag_req_v2。

© www.soinside.com 2019 - 2024. All rights reserved.